javascript中的Object.create:为什么我的代码输出对象而不是名称字符串值
我测试了这个代码段并使用node.js执行javascript中的Object.create:为什么我的代码输出对象而不是名称字符串值,javascript,node.js,Javascript,Node.js,我测试了这个代码段并使用node.js执行 function Person(name) { this.name = name; } john = Object.create(Person); john.name = 'John'; console.log(john.name); 它返回一个人。为什么它不返回“John” 更新:我的问题不是new vs create,我完全知道new和create应该如何使用。我的问题是为什么不能像往常一样设置name属性值 它返回Person。为什么它
function Person(name) {
this.name = name;
}
john = Object.create(Person);
john.name = 'John';
console.log(john.name);
它返回一个人。为什么它不返回“John”
更新:我的问题不是new vs create,我完全知道new和create应该如何使用。我的问题是为什么不能像往常一样设置name属性值
它返回Person
。为什么它不返回“John”
因为Object.create
行创建了一个以Person
函数为原型的对象,Person
函数对象对name
属性有一个令人惊讶的定义,它阻止了对它的写入。(一旦你了解了这个定义,它就有了意义,但一开始它令人惊讶。)
当你这样做的时候,你在创造什么
john = Object.create(Person);
…是一个使用Person
函数作为其底层原型的对象。这不会创建一个Person
实例(将使用Person.prototype
作为其原型),而是创建一个实际使用函数对象Person
本身作为原型的对象
Person
函数有一个名为name
的不可写属性,该属性是函数的名称(该名称尚未在标准中,但将在ES6中定义[目前在§9.2.11中定义],V8已经定义了)。因为该属性不可写,john.name='john'
不做任何事情。(有关不可写属性的详细信息,请参见下文。)
如果您的目标是使用Person.prototype
作为对象的基础原型创建一个新对象,那么您应该执行以下操作:
john = new Person();
或
既然Person
接受了一个论点,你可能会接受
john = new Person('John');
…而不是随后分配给名称
关于不可写属性的更多信息:如果您还没有遇到它们,那么不久前它们被定义为第5版规范的一部分。下面是一个例子:
var parent = {};
Object.defineProperty(parent, "foo", {
writable: false,
value: "original"
});
父对象具有不可写属性,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"
这就是代码中发生的事情<代码>父项
是人
,子项
是约翰
为了解决这个问题:如果我们想在此时在子对象上创建一个可写属性,我们可以,但不能通过赋值,我们必须使用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
,并且是可写的
它返回Person
。为什么它不返回“John”
因为Object.create
行创建了一个以Person
函数为原型的对象,Person
函数对象对name
属性有一个令人惊讶的定义,它阻止了对它的写入。(一旦你了解了这个定义,它就有了意义,但一开始它令人惊讶。)
当你这样做的时候,你在创造什么
john = Object.create(Person);
…是一个使用Person
函数作为其底层原型的对象。这不会创建一个Person
实例(将使用Person.prototype
作为其原型),而是创建一个实际使用函数对象Person
本身作为原型的对象
Person
函数有一个名为name
的不可写属性,该属性是函数的名称(该名称尚未在标准中,但将在ES6中定义[目前在§9.2.11中定义],V8已经定义了)。因为该属性不可写,john.name='john'
不做任何事情。(有关不可写属性的详细信息,请参见下文。)
如果您的目标是使用Person.prototype
作为对象的基础原型创建一个新对象,那么您应该执行以下操作:
john = new Person();
或
既然Person
接受了一个论点,你可能会接受
john = new Person('John');
…而不是随后分配给名称
关于不可写属性的更多信息:如果您还没有遇到它们,那么不久前它们被定义为第5版规范的一部分。下面是一个例子:
var parent = {};
Object.defineProperty(parent, "foo", {
writable: false,
value: "original"
});
父对象具有不可写属性,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"
这就是代码中发生的事情<代码>父项
是人
,子项
是约翰
为了解决这个问题:如果我们想在此时在子对象上创建一个可写属性,我们可以,但不能通过赋值,我们必须使用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
,并且是可写的。FYI如果您替换john=Object.create(Person)代码>与john=新人
您将获得预期结果。可能重复非常非常有趣的问题。@我知道new,我的问题不是new vs create,这就是为什么我不能像往常一样重载name属性。如果替换john=Object.create(Person),仅供参考代码>与john=新人代码>您将得到预期的结果。非常非常有趣的问题可能重复。@我知道new,我的问题不是new vs create,这就是为什么我不能像往常一样重载name属性。答案很好,不知道不可写属性的存在。我仍然感到惊讶,因为我认为如果它不可写,那么在尝试写它时应该会抛出一些错误。@user310291:谢谢!是的,我可能应该提到这一点。在松散模式下,这类事情通常不会抛出错误。在严格模式下,通常是这样。事实上,在严格模式下写入不可写属性通常会抛出一个er