javascript中的Object.create:为什么我的代码输出Object而不是name string value

时间:2014-07-19 12:18:47

标签: javascript node.js

我测试了这个片段并使用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。我的问题是为什么我不能像往常一样设置名称属性值。

1 个答案:

答案 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"

这就是你的代码中发生的事情。 parentPersonchildjohn

只是为了解决这个问题:如果我们想在此时为孩子创建一个可写属性,我们可以,但不是通过作业我们必须使用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,并且是可写的。