JavaScript 核心知识点全解析:变量声明、深浅拷贝、箭头函数与数组方法。
1.const 、var、let这些变量有什么区别?
首先谈var
1.var 可以对一个变量重复声明。作用域是函数。
2.var定义一个变量在函数内部,外部无法使用。
3.存在var变量的函数被调用后,内部变量会被销毁。
4.去掉var 则变成了全局变量,很难被修改,全局变量很难维护、容易被篡改、
5.变量提升。
function test(){console.log(name)var name='前端';}test();会报undefine错误,因为这里相当于:
function test(){var name;console.log(name)name='前端';}let关键字
let不允许重复声明变量。
作用域是块。let的作用域比var的作用域更小,而且let不允许同一个块作用域对一个变量重复声明。
if(true){var name = "syz"console.log(name)}console.log(name)if(true){let age =18console.log(age)}console.log(age)//这里说明了let的作用域比var的作用域更小let没有变量提升。
var没有函数包裹,此时是全局变量会在同一个i上进行操作。
let是块作用域,所以会一个一个创建i。
所以两段代码的差距如此不同。
for(var i = 0;i<5;i++){setTimeout(()=>{console.log(i) },0)}
for(let i = 0;i<5;i++){setTimeout(()=>{console.log(i) },0)}const关键字
const与let类似,区别在于用const声明变量必须初始化,修改声明const变量会报错。
2.深拷贝、浅拷贝是什么?
核心区别在于是否复制对象的深层结构。
浅拷贝:原始类型数据不会被拷贝,但是对象类型的数据会被拷贝,并且可以被新的对象型数据修改。
// 浅拷贝不会改变原始数据类型
var num1=5;
var num2=num1;
num2=9;
console.log(num1)
// 浅拷贝 会改变引用数据类型,因为共享了同一段内存地址
var obj={age:18,name:'前端'
};
var obj2=obj;
obj2.name='数据库';
console.log(obj)深拷贝:完全复制对象的所有层级结构,包括嵌套的对象和数组,拷贝后的数据与原数据完全独立,修改任何一方都不会影响另一方。
function deepCopy(target) {// 步骤1:处理基本类型和nullif (target === null || typeof target !== 'object') {return target;}// 步骤2:创建新容器(区分数组和对象)let result = Array.isArray(target) ? [] : {};// 步骤3:遍历并递归复制for (let key in target) {// 只复制自己的属性(不复制原型链上的)if (target.hasOwnProperty(key)) {result[key] = deepCopy(target[key]); // 递归:深入复制嵌套内容}}return result;
}// 测试:原对象
const obj = { a: 1, b: [2, 3], c: { d: 4 } };
// 深拷贝
const newObj = deepCopy(obj);// 修改新对象,原对象不变
newObj.b[0] = 200;
newObj.c.d = 400;
console.log(obj.b[0]); // 还是2(原对象没改)
console.log(obj.c.d); // 还是4(原对象没改)3.比较
对于原始数据,直接比较他们的值。
对比 null 和 undefined,是的话就会返回 true
判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number
对于引用类型,比较的时候会比较他们的引用地址,虽然他们在堆中存储的对象具有相同属性,但他们可能在被存储在了不同空间。
4.箭头函数 没有 prototype 属性
箭头函数中不支持 arguments 对象。
let sum = function(a,b){return a+b;
};
let sum2 =(a,b) => {return a+b;
};
// 箭头函数map函数:遍历数组的每个元素并做处理
嵌入函数场景:
let ints = [1, 2, 3];
console.log(ints.map(function(i) { return i + 1; })); // [2, 3, 4]
console.log(ints.map((i) => { return i + 1 })); // [2, 3, 4]5.arguments
arguments[0]的用法
// arguments 对象是一个类数组对象(但不是 Array 的实例),
// 因此可以使用中括号语法访问其中的元素
// (第一个参数是 arguments[0],第二个参数是 arguments[1])。
var name='syz';
var message='111';
function sayHi(name, message) {console.log("Hello " + name + ", " + message);
}
sayHi(name,message);function sayhi(name,message){document.writeln("Hello "+arguments[0]+","+arguments[1]);
}
sayhi(name,message)
扩展运算符、apply
var shuzu=[1,2,3,4]var zong =0;function Sum(){for(var i =0 ;i<arguments.length;i++){zong+=arguments[i];}return zong;};console.log(Sum.apply(null,shuzu));console.log(Sum(...shuzu))reduce
计算数组中所有元素的总和
虽然箭头函数不支持使用arguments,但是支持扩展符形参传值。
let sum = (...value)=>{return value.reduce((x,y)=>x+y,0);}console.log(sum(1,2,3,4));
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, cur) => acc + cur, 0);
