1. 闭包
问: 什么是闭包?
- 闭包就是能搞读取其他函数内部变量的函数。
- 闭包指在一个函数内部创建另一个函数,并且内部函数可以访问外部函数的变量。参数以及其他内部函数,即使外部函数已经执行完毕。这种机制使得内部函数保留了对外部作用域的引用,即使外部作用域已经不再活跃。
举个例子:
function exter() {
let k = 0;
function internal() {
k++;
console.log(k);
}
return internal;
}
let counter = exter();
counter();
counter();
counter();
运行结果:
问:闭包有什么用?
- 封装变量
- 保存函数状态
- 实现私有方法和属性
- 延迟执行
- 模块化编程
2. 判断是否循环引用
1. 方法一:
let obj = {};
let obj2 = {};
obj.friend = obj2;
obj2.friend = obj;
let circle = undefined;
// 循环引用
try {
JSON.stringify(obj);
} catch (e) {
circle = true;
console.log(e);
}
如果循环引用会进入catch
2. 方法二:
// 判断循环引用
function isCircle(obj, set = new Set()) {
if (obj == null || typeof obj !== "object") {
return false;
}
if (set.has(obj)) {
return true;
}
set.add(obj);
for (let key in obj) {
if (isCircle(obj[key], set)) {
return true;
}
}
return false;
}
3. 认识迭代器
迭代就是指可以从一个数据集中按照一定的顺序,不断取出数据的过程。
迭代器是指能调用next方法实现迭代的一个对象,该方法返回一个具有两个属性的对象。
- value: 迭代对象的值
- done: 表示是否已经取出所有数据了。 false 表示还有数据,true表示已经全部取出
原生具有迭代器接口的数据结构有: Array String Set Map, 特殊类数组对象: arguments,NodeList等.
给对象添加迭代:
1. 给类数组添加迭代
类数组:什么是类数组 只包含使用从零开始,且自然递增的整数做键名,并且定义了length表示元素个数的对象,我们就认为它是类数组对象
let obj3 = {
0: "小明",
1: "小红",
2: "小花",
length: 3,
};
obj3[Symbol.iterator] = function fn() {
let index = 0;
return {
next: () => {
return {
value: this[index++],
done: index > this.length,
};
},
};
};
2. 给对象添加迭代器
var [ a, b ] = { a : '小明' , b : ' 小量 ' }
let obj3 = {
name: "小明",
name1: "小红",
name2: "小花",
};
obj3[Symbol.iterator] = function () {
return Object.values(this)[Symbol.iterator]();
};
for (let key of obj3) {
console.log(key);
}
3. 查看数组的迭代
let arr = [1, 2, 3, 4, 5];
let iterator = arr[Symbol.iterator]();
let n = iterator.next;
let k = n.call(iterator);
k = n.call(iterator);
k = n.call(iterator);
k = n.call(iterator);
console.log(k);
4. 深拷贝和浅拷贝
深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。
参考地址:百度一面:你来谈谈JS中的浅拷贝与深拷贝 (baidu.com)
注意:赋值不属于拷贝
浅拷贝的方法:
1. es6 的扩展运算符
2. Object.assign 方法
深拷贝的方法:
1. 通过JSON.parse(JSON.stringify(obj))
局限性:不能复制方法
2. 递归复制所有层级
function deepClone(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
let clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
clone[key] = deepClone(obj[key]);
}
return clone;
}