JavaScript对象属性复制原理:修改源对象方法为何不影响复制结果?
为什么修改原对象的方法不会影响已复制到原型的方法?
我懂你的困惑——按道理说复制引用类型的话,修改原对象应该会影响复制后的对象才对,但这里却没生效,对吧?咱们一步步拆解问题所在:
你的extend函数做了什么?
看这段核心代码:
destination[k] = source[k];
当你把circle.area赋值给RoundButton.prototype.area时,你其实是把函数对象的引用值复制了一份。这时候,circle.area和RoundButton.prototype.area就像两个独立的指针,同时指向同一个函数对象,但它们之间没有绑定关系。
打个比方:你有一个抽屉(原函数对象),circle.area是一把指向这个抽屉的钥匙,你复制了一把新钥匙给RoundButton.prototype.area。现在你把原来的抽屉换成了一个新的(重新赋值circle.area = 新函数),但新钥匙还是指向原来的旧抽屉,自然不会跟着变。
怎么实现你想要的“同步修改”效果?
如果你希望修改circle的方法后,RoundButton原型上的方法也自动更新,那你需要用原型链继承,而不是复制属性。让RoundButton.prototype的原型直接指向circle,这样当访问RoundButton.prototype.area时,会沿着原型链去circle上查找,自然会拿到最新的方法。
修改后的代码示例:
var circle = { area: function() { return Math.PI * this.radius * this.radius; } }; function RoundButton(radius) { this.radius = radius; } // 让RoundButton的原型继承自circle RoundButton.prototype = Object.create(circle); // 别忘了修正构造函数的指向(否则instanceof会出问题) RoundButton.prototype.constructor = RoundButton; console.log(RoundButton.prototype.area); // ƒ () { return Math.PI * this.radius * this.radius;} circle.area = function() { return Math.PI * this.radius * this.radius * this.radius; } console.log(RoundButton.prototype.area); // ƒ () { return Math.PI * this.radius * this.radius * this.radius;}
总结一下区别
- 属性复制:相当于给目标对象独立分配了一份属性值的引用,源对象和目标对象的属性是“各玩各的”,修改源对象的属性指向不会影响目标对象。
- 原型链继承:目标对象的原型直接关联源对象,访问属性时会动态查找原型链,源对象的属性变化会实时反映到目标对象的属性访问中。
内容的提问来源于stack exchange,提问作者Dharmendra
相关产品推荐
相关产品推荐

