学在前面
- Map、WeakMap、Set
- for in 和 for of 的区别:
- for in 语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性(只能遍历对象)。
- for...of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句
- for of 循环的是value, for in 循环的是key值
- for in 遍历的属性包括原型, for of 不包括原型上的属性
- for in 遍历数组可能顺序不同
- 判断变量的类型(typeof instanceof constructor Object.prototype.toString.call)
简单的深拷贝
const checkType = (type) => (val) => Object.prototype.toString.call(val) === `[object ${type}]`;
const utils = {};
const needArray = ['Object', 'Array', 'String', 'Number', 'Boolean', 'Null', 'Undefined', 'Null', 'Symbol', 'Error', 'RegExp', 'Set', 'Map', 'WeakMap','Date'];
needArray.forEach((methods) => {
utils[`is${methods}`] = checkType(methods);
})
const deepClone = (arr) => {
if (typeof arr !== 'object' || arr == null) return arr;
let result = new arr.constructor();
for (let key in arr) {
if (arr.hasOwnProperty(key)) {
result[key] = deepClone(arr[key]);
}
}
return result;
}
let obj = {
name: 'zhangsan',
d: {
x: 100,
y: 200,
z: [1, {name: '456'}]
},
count: 1,
flag: true,
c: null,
m: undefined,
h: BigInt(1111)
}
let obj1 = deepClone(obj);
- 上面的实现会遇到一个问题,如果一个对面类型的属性值是自己或者赋的值是一个对象里面的属性是自己,就会出现死循环这种情况
let obj = {
name: 'zhangsan',
}
obj.child = obj
deepClone(obj)
const deepClone = (arr, weakMap = new WeakMap()) => {
if (typeof arr !== 'object' || arr == null) return arr;
if (!utils.isWeakMap(arr)) {
weakMap = new WeakMap();
}
let result = new arr.constructor();
if (weakMap.has(arr)) {
return weakMap.get(arr);
}
weakMap.set(arr, result);
for (let key in arr) {
if (arr.hasOwnProperty(key)) {
result[key] = deepClone(arr[key], weakMap)
}
}
return result
}
完整版的deepClone(这里需要对里面的数据进行特殊处理:Symbol, Error, RegExp, Set, Map,Date)
const checkType = (type) => (val) => Object.prototype.toString.call(val) === `[object ${type}]`;
const utils = {};
const needArray = ['Object', 'Array', 'String', 'Number', 'Boolean', 'Null', 'Undefined', 'Null', 'Symbol', 'Error', 'RegExp', 'Set', 'WeakMap', 'Map','Date'];
needArray.forEach((methods) => {
utils[`is${methods}`] = checkType(methods);
})
const deepClone = (arr, weakMap = new WeakMap()) => {
if (typeof arr !== 'object' || arr == null) return arr;
if (!utils.isWeakMap(arr)) {
weakMap = new WeakMap();
}
if (utils.isSymbol(arr)) return Object(Symbol.prototype.valueOf.call(arr));
if (utils.isDate(arr)) return new arr.constructor(arr);
if (utils.isError(arr)) return new arr.constructor(arr.message);
if (utils.isRegExp(arr)) return new RegExp(arr);
let result = new arr.constructor();
if (utils.isSet(arr)) {
arr.forEach(item => result.add(deepClone(item, weakMap)))
return result;
}
if (utils.isMap(arr)) {
arr.forEach((key, value) => {
result.set(deepClone(key, weakMap), deepClone(value, weakMap))
})
return result;
}
if (utils.isArray(arr) || utils.isObject(arr)) {
if (weakMap.has(arr)) {
return weakMap.get(arr);
}
weakMap.set(arr, result);
for (let key in arr) {
if (arr.hasOwnProperty(key)) {
result[key] = deepClone(arr[key], weakMap)
}
}
return result
}
}
let obj = {
name: 'zhangsan',
d: {
x: 100,
y: 200,
z: [1, {name: '456'}]
},
count: 1,
flag: true,
c: null,
m: undefined,
h: BigInt(1111),
s: Symbol('s'),
t: new Date(),
e: new Error('sb'),
r: /\w*/gi,
p: new Map([[0, '红'], [1, '太'], [2, '狼'], ['美', 4], ['羊', 5], ['羊', 6], [{name: '1111'}, '1111']]),
}
console.log(deepClone(obj))