前言
日志,各位看官就当乐子看吧。
正经人谁写日记啊?!! ——鹅城县长
结合理解,用短篇幅回答一个面试题
浅拷贝和深拷贝
原文:https://vue3js.cn/interview/JavaScript/copy.html#%E4%B8%80%E3%80%81%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E5%AD%98%E5%82%A8
浅拷贝:指一个对象的副本,副本中的属性与源对象的属性共享相同引用(指向相同的底层值);
深拷贝:不共享,也就是当改变源或副本时,可以保证不对其他对象也产生变化。
进阶
复制操作方法哪些是浅拷贝
扩展运算符
、Array.prototype.concat()
、Array.prototype.slice()
、Array.from()
、Object.assign()
、Object.create()
如何实现深拷贝?
-
JSON.stringify
先将数据字符串化,然后通过JSON.parse生成对象并赋值。
缺点:会忽略如函数、Symbol、undefined等类型的属性 -
代码实现,基于递归
function deepClone(obj, hash = new WeakMap()) {
if (obj == null) return obj; // 如果是null或者undefined我就不进行拷贝操作
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// 可能是对象或者普通的值 如果是函数的话是不需要深拷贝
if (typeof obj !== "object") return obj;
// 是对象的话就要进行深拷贝
if (hash.has(obj)) return hash.get(obj);
// 找到的是所属类原型上的constructor,创建相同类型数据
let cloneObj = new obj.constructor();
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 实现一个递归拷贝
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
其中WeakMap
是处理循环引用的情况,避免栈溢出。就是以下这种情况。
lain.itself=lain
deepClone(lain)
建议看深拷贝的实现(其中,有对拷贝代码的步步完善过程)。最后我有个问题,数据的循环引用的应用场景是什么?
- structuredClone()
MDN中提到了这个方法,也支持循环引用,
let original = { name: "MDN"};
original.itself = original;
let clone = structuredClone(original);
console.log(clone !== original); // true
console.log(clone.name === "MDN"); // true
console.log(clone.itself === clone); // true
缺点是输入值要求必须可以序列化,还有兼容问题
let original = { name: "MDN", A: undefined, B: function(){} };
let clone = structuredClone(original); // Uncaught DOMException: ... function(){} could not be cloned.
文中提到了"它是浏览器和任何其他实现了 window 这样全局对象的 JavaScript 运行时的一个特性",意思应该是存在兼容性问题,可以引入core-js
解决。
其他
==相等
和===全等
,以及适用场景
==相等的判断会出现类型转换:
- 只有不同类型数据比较,才会发生隐式转换;
- 两个操作数都是基本类型,则字符串和布尔类型会转换成数值;
- 仅单个操作数是对象,则会获取对象原始值,再依据1,2做对比;
- 两个数都是对象,则判断他们是否是相同引用,相同则相等;
- null和undefined相等;
- 任一数是NaN,结果都是false
===全等,则是不转换类型,直接判断是否相等。其中null、undefined只和自身全等。
场景:当需要判断对象属性是否等于null和undefined时,使用==
。其余建议都使用===
。
for…in 遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。阮一峰老师的博客有些,对象的扩展
for…of 主要用于依赖索引顺序的遍历,Array
总结
学习Proxy
以及基于Proxy实现响应式系统