您的两个代码示例通常是等效的(除了一些与问题无关的小细节)。
这个...
Object.create(EmployeeNew)
...创建一个以EmployeeNew
对象为原型的新对象。所以print
和init
函数是共享的。
console.log(empNew1.init === empNew2.init); // true
console.log(empNew1.print === empNew2.print); // true
为了进一步说明,这是一个采用以下步骤的示例...
- 创建一个
EmployeeNew
对象以供使用Object.create
- 使用创建 2 个独特的对象
Object.create
- 验证新对象是否可以使用提供的功能
EmployeeNew
- 添加一个新函数到
EmployeeNew
- 查看步骤 2 中的对象是否可以使用该新功能
第 1 步:创建EmployeeNew
对象
var EmployeeNew = {
init: function (name) { this.name = name; },
print: function () {
console.log(this.name);
}
};
第 2 步:使用创建 2 个唯一对象Object.create
var empNew1 = Object.create(EmployeeNew),
empNew2 = Object.create(EmployeeNew)
第 3 步:验证新对象是否可以使用EmployeeNew
empNew1.init("jack");
empNew1.print();
empNew2.init("jack");
empNew2.print();
第四步:添加新功能EmployeeNew
EmployeeNew.foo = function() {
console.log( 'Foo was invoked' );
};
第 5 步:查看第 2 步中的对象是否可以使用该新功能
empNew1.foo(); // logs 'Foo was invoked'
empNew2.foo(); // logs 'Foo was invoked'
因此,您可以看到empNew1
并empNew2
能够观察到 的变化EmployeeNew
。这是因为当我们EmployeeNew
作为第一个参数传递给 时Object.create
,我们创建了一个新对象,并EmployeeNew
设置prototype
为该对象的。
简单来说,当我们查找一个属性时,例如 on empNew1
,如果empNew1
没有该属性,它会自动查找其原型以查看该属性是否存在于该对象上。如果是这样,它会使用它。
关于你的评论...
“......假设,如果创建 this.name 作为属性(名称:“”)是名称属性也将被视为原型......”
是的,如果我们这样做...
EmployeeNew.name = "unknown"
...然后该属性将在所有具有EmployeeNew
原型对象的实例之间共享。
但
因为.name
原型上的属性是不可变的原始值(字符串),如果我们尝试写入该属性,会发生该.name
属性自动直接添加到实例的情况。
继续上面的例子......
EmployeeNew.name = "unknown";
现在之前创建的实例将引用该属性...
empNew1.name; // "unknown"
empNew2.name; // "unknown"
...但是现在让我们在一个实例上更新属性...
empNew1.name = "bubba";
empNew1.name; // "bubba"
empNew2.name; // "unknown"
这是因为empNew1
now 有自己的.name
属性来引用"bubba"
. 这会在 的原型上隐藏属性,因此对该属性的搜索永远不会扩展到原型对象。.name
empNew1
由于empNew2
没有分配 a .name
,它仍然会查找该属性的原型。