我测试了这个片段并使用node.js
执行function Person(name) {
this.name = name;
}
john = Object.create(Person);
john.name = 'John';
console.log(john.name);
它返回Person。为什么不归还' John' ?
更新:我的问题不是关于new vs create,我完全知道应该如何使用new和create。我的问题是为什么我不能像往常一样设置名称属性值。
答案 0 :(得分:4)
返回
Person
。为什么不返回'John'
?
因为Object.create
行创建了一个以Person
函数为原型的对象,而Person
函数对象有一个令人惊讶的name
属性定义,阻止了写给它。 (一旦你了解它,这个定义就有意义,但一开始就令人惊讶。)
当您执行
时创建的内容john = Object.create(Person);
...是一个使用Person
函数作为其底层原型的对象。这不会创建Person
实例(使用Person.prototype
作为其原型),它会创建一个实际使用函数对象Person
本身的对象原型。
Person
函数有一个名为name
的不可写属性,它是函数的名称(这还不在标准中,但它将在ES6中[当前它在§中定义] draft spec]的9.2.11和V8已经完成了。由于该属性不可写,john.name = 'John'
不执行任何操作。 (有关下面不可写属性的更多信息。)
如果您的目标是使用Person.prototype
创建一个新对象作为对象的基础原型,那么您可以:
john = new Person();
或
john = Object.create(Person.prototype);
由于Person
接受了一个论证,你可能会做
john = new Person('John');
...而不是之后分配给name
。
有关不可写属性的更多信息:如果您还没有遇到它们,那么它们被定义为第5版规范的一部分。这是一个例子:
var parent = {};
Object.defineProperty(parent, "foo", {
writable: false,
value: "original"
});
parent
对象具有不可写属性foo
:
console.log(parent.foo); // "original"
parent.foo = "bar";
console.log(parent.foo); // "original"
如果我们使用parent
作为原型,即使在子对象上,我们仍然无法写入foo
:
var child = Object.create(parent);
console.log(child.foo); // "original"
child.foo = "bar";
console.log(child.foo); // "original"
这就是你的代码中发生的事情。 parent
为Person
,child
为john
。
只是为了解决这个问题:如果我们想在此时为孩子创建一个可写属性,我们可以,但不是通过作业我们必须使用defineProperty
:
Object.defineProperty(child, "foo", {
writable: true,
value: child.foo // (just sets the initial value)
});
console.log(child.foo); // "original"
child.foo = "bar";
console.log(child.foo); // "bar"
现在child
有一个名为foo
的拥有的属性,它隐藏(隐藏)其原型的foo
,并且是可写的。