深克隆和浅克隆
1.如何复制对象?
function anotherFunction() { /*..*/ } var anotherObject = { c: true }; var anotherArray = []; var myObject = { a: 2, b: anotherObject, // 引用, 不是复本! c: anotherArray, // 另一个引用! d: anotherFunction }; anotherArray.push( anotherObject, myObject );
如何准确地表示myObject的复制呢?
首先,我们应该判断它是浅复制还是深复制。对于浅拷贝来说,复制出的新对象中a的值会复制旧对象中a的值,也就是2,但是新对象中b、c、d三个属性其实只是三个引用,它们和旧对象中b、c、d引用的对象是一样的
没有很好的解决方案:
1.对于JSON安全(也就是说可以被序列化为一个JSON字符串并且可以根据这个字符串解析出一个结构和值完全一样的对象)的对象来说,有一种巧妙的复制方法:
var newObj = JSON.parse( JSON.stringify( someObj ) );
2.相比深复制,浅复制非常易懂并且问题要少得多,所以ES6定义了Object.assign(..)方法来实现浅复制。Object.assign(..)方法的第一个参数是目标对象,之后还可以跟一个或多个源对象。它会遍历一个或多个源对象的所有可枚举的自有键很快会并把它们复制(使用=操作符赋值)到目标对象,最后返回目标对象 。
var newObj = Object.assign( {}, myObject ); newObj.a; // 2 newObj.b === anotherObject; // true newObj.c === anotherArray; // true newObj.d === anotherFunction; // true
2.属性的描述符
1.getOwnPropertyDescriptor
var myObject = { a:2 }; Object.getOwnPropertyDescriptor( myObject, "a" ); // { // value: 2, // writable: true, // enumerable: true, // configurable: true // }
三个特性:writable(可写)、enumerable(可枚举)和configurable(可配置)
2.defineProperty
var myObject = {}; Object.defineProperty( myObject, "a", { value: 2, writable: true, configurable: true, enumerable: true } ); myObject.a; // 2