We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。
可以使用for in、Object.assign、扩展运算符 ...、Array.prototype.slice()、Array.prototype.concat()进行浅拷贝,例如:
for in
Object.assign
扩展运算符 ...
Array.prototype.slice()
Array.prototype.concat()
let obj = { name: 'Yvette', age: 18, hobbies: ['reading', 'photography'] } let target = {}; let obj2 = Object.assign(target, obj); let obj3 = {...obj}; obj.name = 'Jack'; obj.hobbies.push('coding'); console.log(obj); //{ name: 'Jack', age: 18,hobbies: [ 'reading', 'photography', 'coding' ] } console.log(target);//{ name: 'Yvette', age: 18,hobbies: [ 'reading', 'photography', 'coding' ] } console.log(obj2);//{ name: 'Yvette', age: 18,hobbies: [ 'reading', 'photography', 'coding' ] } console.log(obj3);//{ name: 'Yvette', age: 18,hobbies: [ 'reading', 'photography', 'coding' ] }
可以看出浅拷贝只最第一层属性进行了拷贝,当第一层的属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是复杂数据类型,那么新对象和原对象的属性值其指向的是同一块内存地址。
深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。
1、深拷贝最简单的实现是: JSON.parse(JSON.stringify(obj))
JSON.parse(JSON.stringify(obj))是最简单的实现方式,但是有一些缺陷:
JSON.parse(JSON.stringify(obj))
let obj = { age: 18, date: new Date() }; let objCopy = JSON.parse(JSON.stringify(obj)); console.log('obj', obj); console.log('objCopy', objCopy); console.log(typeof obj.date); // object console.log(typeof objCopy.date); // string
let obj = { age: 18, reg: new RegExp('\\w+'), err: new Error('error message') }; let objCopy = JSON.parse(JSON.stringify(obj)); console.log('obj', obj); console.log('objCopy', objCopy);
let obj = { age: 18, fn: function () { console.log('fn'); }, hh: undefined }; let objCopy = JSON.parse(JSON.stringify(obj)); console.log('obj', obj); console.log('objCopy', objCopy);
let obj = { age: 18, hh: NaN, isInfinite: 1.7976931348623157E+10308, minusInfinity: -1.7976931348623157E+10308 }; let objCopy = JSON.parse(JSON.stringify(obj)); console.log('obj', obj); console.log('objCopy', objCopy);
function Person(name) { this.name = name; } let obj = { age: 18, p1: new Person('lxcan') }; let objCopy = JSON.parse(JSON.stringify(obj)); console.log('obj', obj); console.log('objCopy', objCopy); console.log(obj.p1.__proto__.constructor === Person); // true console.log(objCopy.p1.__proto__.constructor === Person); // false console.log(objCopy.p1.__proto__.constructor === Object); // true
let obj = { age: 18 }; obj.obj = obj; let objCopy = JSON.parse(JSON.stringify(obj)); console.log('obj', obj); console.log('objCopy', objCopy);
如果拷贝的对象不涉及上面的情况,可以使用JSON.parse(JSON.stringify(obj))实现深拷贝。
2、deepClone 实现深拷贝
function
RegExp
Date
拓展: WeakMap 其键必须是对象,而值可以是任意的。其持有的每个键是“弱引用”,这意味着在没有其他引用存在时垃圾回收能正确进行,其持有的每个键只有在其没有被回收时才是有效的。
正由于这样的弱引用,WeakMap 的 key 是不可枚举的 (没有方法能给出所有的 key)。如果key 是可枚举的话,其列表将会受垃圾回收机制的影响,从而得到不确定的结果。因此,如果你想要这种类型对象的 key 值的列表,应该使用 Map。
function deepClone(obj, hash = new WeakMap()) { //递归拷贝 if (obj instanceof RegExp) return new RegExp(obj); if (obj instanceof Date) return new Date(obj); // 如果是基本数据类型和'function'类型的话直接返回 if (obj === null || typeof obj !== 'object') { return obj; } if (hash.has(obj)) { return hash.get(obj); } /** * 如果obj是数组,那么 obj.constructor 是 [Function: Array] * 如果obj是对象,那么 obj.constructor 是 [Function: Object] */ let t = new obj.constructor(); hash.set(obj, t); for (let key in obj) { //递归 if (obj.hasOwnProperty(key)) {//是否是自身的属性 t[key] = deepClone(obj[key], hash); } } return t; }
测试代码
const test = { a: { name: "hello", age: 21 }, fn: function(){ console.log("go"); } }; const res = deepClone(test); res.a.age = 25; console.log(test); console.log(res); // { a: { name: 'hello', age: 21 }, fn: [Function: fn] } // { a: { name: 'hello', age: 25 }, fn: [Function: fn] }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
浅拷贝
浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。
可以使用
for in
、Object.assign
、扩展运算符 ...
、Array.prototype.slice()
、Array.prototype.concat()
进行浅拷贝,例如:可以看出浅拷贝只最第一层属性进行了拷贝,当第一层的属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是复杂数据类型,那么新对象和原对象的属性值其指向的是同一块内存地址。
深拷贝
深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。
深拷贝实现
JSON.parse(JSON.stringify(obj))
是最简单的实现方式,但是有一些缺陷:1、如果json里面有时间对象,则序列化结果:时间对象=>字符串的形式;
2、如果json里有RegExp、Error对象,则序列化的结果将只得到空对象 RegExp、Error => {};
3、如果json里有 function,undefined,则序列化的结果会把 function,undefined 丢失;
4、如果json里有NaN、Infinity和-Infinity,则序列化的结果会变成null;
5、如果json里有对象是由构造函数生成的,则序列化的结果会丢弃对象的 constructor;
6、如果对象中存在循环引用的情况也无法实现深拷贝
如果拷贝的对象不涉及上面的情况,可以使用
JSON.parse(JSON.stringify(obj))
实现深拷贝。function
类型,直接返回RegExp
或者Date
类型,返回对应类型拓展:
WeakMap 其键必须是对象,而值可以是任意的。其持有的每个键是“弱引用”,这意味着在没有其他引用存在时垃圾回收能正确进行,其持有的每个键只有在其没有被回收时才是有效的。
正由于这样的弱引用,WeakMap 的 key 是不可枚举的 (没有方法能给出所有的 key)。如果key 是可枚举的话,其列表将会受垃圾回收机制的影响,从而得到不确定的结果。因此,如果你想要这种类型对象的 key 值的列表,应该使用 Map。
测试代码
参考文章
The text was updated successfully, but these errors were encountered: