深度复制对象属性

先来看一个例子

function extend(o, p) {
    var names = Object.getOwnPropertyNames(p);
    for (var i = 0; i < names.length; i++) {
        if (names[i] in o) {
            continue;
        } 
        o[names[i]] = p[names[i]];
    }
    return o;
}
var p = Object.defineProperties({}, {
    x: { value: 1, writable: false, enumerable: false, configurable: true },
    y: { value: 2, writable: false, enumerable: false, configurable: true },
    r: {
        get: function() { return Math.floor(Math.random() * 256) },
        enumerable: false,
        configurable: false
    }
});
var o = extend({}, p);
console.log(o.r);  //输出0-256之间的一个随机数
o.x = 2;   
console.log(o.x);  // 2
for (var prop in o)
    console.log(prop);  //输出 x,y,r


现在我们来分析结果

首先,extend()函数将p的所有自有属性(包括可枚举和不可枚举的属性)复制给o。若o有相同的属性,则不复制

然后o得到了x, y, r三个属性。并且,我们可以改变o.x的值,o中,x, y, r三个属性是可枚举的。但是,我们在定义对象p时,x, y, z三个属性都是定义为不可枚举,且x,y两个属性是不可写的。

这就说明,函数extend()在复制时,并没有进行属性特性的深度复制


Object.getOwnPropertyDescriptor()


一个属性包括四个特性,它们分别是value, writable, enumerable, configurable。而”属性描述符“对象的属性和四个属性特性是同名的,即”属性描述符“对象有这四个属性。我们可以用Object.getOwnPropertyDescriptor()获得某个对象特定属性的描述符,从名字可以看书,它只能得到自由描述符。通过Object.getOwnPropertyDescriptor()和 Object.defineProperty()的配合,就可以深度复制一个对象的属性

看下面的结果

var p = Object.defineProperties({}, {
    x: { value: 1, writable: false, enumerable: false, configurable: true },
    y: { value: 2, writable: false, enumerable: false, configurable: true },
    r: {
        get: function() { return Math.floor(Math.random() * 256) },
        enumerable: false,
        configurable: false
    }
});
 
Object.defineProperty(Object.prototype,
    "extend",  
    {
        writable: true,
        enumerable: false,
        configurable: true,
        value: function(o) {
            var names = Object.getOwnPropertyNames(o);
            for(var i = 0; i < names.length; i++) {
                if (names[i] in this) continue;
                var desc = Object.getOwnPropertyDescriptor(o,names[i]);
                Object.defineProperty(this, names[i], desc);
            }
        }
    });
    
var o = {};
o.extend(p);
console.log(o.r); // 输出0-256之间的一个随机数  
console.log(o.x);  // 输出1
o.x = 2;
console.log(o.x);   // 输出1
for (var prop in o)
    console.log(prop);  // 没有输出

我们给Object.prototype添加一个不可枚举的extend()方法,所有对象都会继承这个方法。

同样的p,经过重新定义的函数复制后,结果很明显,这已经达到我们的目的了。


注:参考《JavaScript权威指南》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值