javascript中的Object.create:为什么我的代码输出Object而不是名称string值?
我testing了这个片段,并用node.js执行
function Person(name) { this.name = name; } john = Object.create(Person); john.name = 'John'; console.log(john.name);
它返回Person。 为什么不返回“约翰”?
更新:我的问题不是关于新vs创build,我完全知道应该如何使用新build和创build。 我的问题是为什么我不能像往常一样设置名称属性值。
它返回
Person
。 为什么不返回'John'
?
由于该Object.create
行创build一个Person
函数作为其原型的对象,并且Person
函数对象有一个令人惊讶的name
属性的定义,阻止您写入它。 (一旦你知道这个定义是有道理的,但起初它是令人惊讶的。)
当你做什么时你正在创造什么
john = Object.create(Person);
…是一个使用Person
函数作为其基础原型的对象。 这不会创build一个Person
实例 (将使用Person.prototype
作为其原型),它会创build一个实际使用函数对象Person
本身作为原型的对象。
Person
函数有一个叫做name
的非可写属性,它是函数的名字(这个还没有在标准中,但是在ES6中[现在在草稿的9.2.2节中定义],而V8是它已经)。 由于该属性不可写 , john.name = 'John'
不起任何作用。 (更多关于下面的不可写属性。)
如果你的目标是用Person.prototype
创build一个新的对象作为对象的基础原型,你可以这样做:
john = new Person();
要么
john = Object.create(Person.prototype);
既然Person
接受一个论点,你可能会这么做
john = new Person('John');
…而不是后来分配name
。
关于不可写属性的更多信息:如果还没有碰到它们,那么它们在第五版规范中被定义为后面的一部分。 这是一个例子:
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
。
只是想了解一下:如果我们想在这个时候为孩子创build一个可写的属性,我们可以,但是不能通过赋值,我们必须使用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
,并且是可写的。