闭包
闭包(closure)指有权访问另一个函数作用域中变量的函数。
被访问的局部变量所在作用域的函数就叫闭包函数。
// 闭包:fun 这个函数作用域 访问了另外一个函数 fn 里面的局部变量num
// fn 外面的作用域也可以访问fn内部的局部变量
// 闭包的主要作用:延伸了变量的作用范围
function fn() {
var num = 10
// function fun() {
// console.log(num)
// }
// return fun
return function () {
console.log(num)
}
}
let f = fn()
f()
fn()()
浅拷贝和深拷贝
首先,我们要知道 js 有两种数据类型,基础数据类型和引用数据类型。基础数据类型都是按值访问的,我们可以直接操作保存在变量中的实际的值。而引用数据类型如 Array 和 Object,我们不能直接操作对象的堆内存空间。引用数据类型的值都是按引用访问的,即保存在变量对象中的一个地址,指向存储在堆内存中的对象。
浅拷贝和深拷贝是指拷贝的两种情况。浅拷贝只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做浅拷贝(浅复制)。
比如:
var a = {name: 'Tom', age: 18};
var b = a; // 浅拷贝
b.name = 'Jerry';
console.log(a.name); // Jerry
可以看到,修改 b 的 name 属性后,a 的 name 属性也跟着变了。这是因为 b 只是复制了 a 的地址,并没有创建一个新的对象。
深拷贝则是对目标对象及其所有子对象进行递归复制,并返回一个新对象。这样就不会影响原对象的值了。我们把这种拷贝叫做深拷贝(深复制)。
比如:
var a = {name: 'Tom', age: 18};
var b = JSON.parse(JSON.stringify(a)); // 深拷贝
b.name = 'Jerry';
console.log(a.name); // Tom
可以看到,修改 b 的 name 属性后,a 的 name 属性没有变化。这是因为 b 是通过 JSON 方法创建了一个新的对象,并复制了 a 的所有属性。
JSON 方法并不是最完美的深拷贝方法,它有一些局限性和缺点。比如它不能处理函数、循环引用、日期等特殊情况。如果要实现更完善的深拷贝方法,可以使用一些第三方库或者自己编写递归函数来实现。
编写递归函数实现深拷贝:
function deepClone(obj) {
// 非对象和null直接返回
if (typeof obj !== 'object' || obj === null) {
return obj;
}
// 创建新对象,考虑数组的情况
const newObj = Array.isArray(obj) ? [] : {};
// 遍历对象的属性,进行递归拷贝
for (let key in obj) {
newObj[key] = deepClone(obj[key]);
}
return newObj;
}