JavaScript Object.create——继承嵌套属性
我遇到了 Douglas Crockfords Object.create 方法的一个特点,我希望有人能够解释一下:
如果我创建一个对象 - 比如说“人” - 使用对象文字表示法,然后使用 Object.create 创建一个新的对象对象 - 比如说“anotherPerson” - 它继承了初始“person”对象的方法和属性。
如果我随后更改第二个对象“anotherPerson”的名称值,它也会更改初始“person”对象的名称值。
仅当属性嵌套时才会发生这种情况,此代码应该让您了解我的意思:
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
};
// initiate new 'person' object
var person = {
name: {
first: 'Ricky',
last: 'Gervais'
},
talk: function() {
console.log('my name is ' + this.name.first + ' ' + this.name.last);
}
}
// create anotherPerson from person.prototype
var anotherPerson = Object.create(person);
// change name of anotherPerson
anotherPerson.name.first = 'Stephen';
anotherPerson.name.last = 'Merchant';
// call talk method of both 'person' and 'anotherPerson' objects
person.talk(); // oddly enough, prints 'Stephen Merchant'
anotherPerson.talk(); // prints 'Stephen Merchant'
如果我要在没有嵌套的情况下存储名称值,则不会发生这种奇怪的行为 - 例如,
// initiate new 'person' object
var person = {
firstName: 'Ricky',
lastName: 'Gervais',
talk: function() {
console.log('my name is ' + this.firstName + ' ' + this.lastName);
}
}
// create anotherPerson from person.prototype
var anotherPerson = Object.create(person);
// change name of anotherPerson
anotherPerson.firstName = 'Stephen';
anotherPerson.lastName = 'Merchant';
// call talk method of both 'person' and 'anotherPerson' objects
person.talk(); // prints 'Ricky Gervais'
anotherPerson.talk(); // prints 'Stephen Merchant'
此嵌套问题似乎不会发生当使用带有构造函数和“new”关键字的经典继承风格时。
如果有人能够解释为什么会发生这种情况,我将不胜感激!
I've come across a peculiarity with Douglas Crockfords Object.create method which I'm hoping someone might be able to explain:
If I create an object - say 'person' - using object literal notation then use Object.create to create a new object - say 'anotherPerson' - which inherits the methods and properties from the initial 'person' object.
If I then change the name values of the second object - 'anotherPerson' - it also changes the name value of the initial 'person' object.
This only happens when the properties are nested, this code should give you an idea of what I mean:
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
};
// initiate new 'person' object
var person = {
name: {
first: 'Ricky',
last: 'Gervais'
},
talk: function() {
console.log('my name is ' + this.name.first + ' ' + this.name.last);
}
}
// create anotherPerson from person.prototype
var anotherPerson = Object.create(person);
// change name of anotherPerson
anotherPerson.name.first = 'Stephen';
anotherPerson.name.last = 'Merchant';
// call talk method of both 'person' and 'anotherPerson' objects
person.talk(); // oddly enough, prints 'Stephen Merchant'
anotherPerson.talk(); // prints 'Stephen Merchant'
If I were to store the name values without nesting then this odd behaviour does not occur -- e.g.
// initiate new 'person' object
var person = {
firstName: 'Ricky',
lastName: 'Gervais',
talk: function() {
console.log('my name is ' + this.firstName + ' ' + this.lastName);
}
}
// create anotherPerson from person.prototype
var anotherPerson = Object.create(person);
// change name of anotherPerson
anotherPerson.firstName = 'Stephen';
anotherPerson.lastName = 'Merchant';
// call talk method of both 'person' and 'anotherPerson' objects
person.talk(); // prints 'Ricky Gervais'
anotherPerson.talk(); // prints 'Stephen Merchant'
This nesting issue doesn't seem to occur when using a classical style of inheritance with a constructor function and the 'new' keyword.
I'd be much appreciative if anyone's able to explain why this occurs!?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
发生这种情况是因为
anotherPerson.name
是一个对象,并且它存储在原型链的上部,即原始person
对象上:您可以通过将一个新对象分配给新创建的对象的
name
属性:That happens because
anotherPerson.name
is an object and it is stored upper in the prototype chain, on the originalperson
object:You can avoid this by assigning a new object to the
name
property of the newly created object:问题是 Object.create 只进行浅复制,而不是深复制,因此 person.name 和 anotherPerson.name 都指向同一个 Object 实例。
已编辑
虽然
person.name === anotherPerson.name
确实如此,但我对为什么这是正确的解释是不正确的。正确的解释请参阅@CMS 的答案。The problem is that Object.create only does a shallow copy, not a deep copy, so person.name and anotherPerson.name both point to the same Object instance.
Edited
While it's true that
person.name === anotherPerson.name
, my explanation for why this is true is incorrect. See @CMS's answer for the correct explanation.name
属性不被复制的原因是因为 JavaScript 中的对象字面量始终是引用,因此引用被复制(而不是其内容)......所以这不是因为它在原型中更深层次链或者因为它正在执行浅复制。The reason the
name
attribute isn't copied is because object literals in JavaScript are always references, therefore the reference is copied (not its content) ... so it is not because it is deeper in the prototype chain or because it's doing a shallow copy.