我在下面创建了两个员工类,一个使用构造函数,另一个使用 JSON 表示法。在构造函数中,print
函数是由原型(prototype)创建的,因此只会保留一个副本,对象(emp1
和 emp2
)共享此 打印
功能。
问题:在 JSON 表示法(EmployeeNew
)中,print
函数是否仅作为一个副本保存在内存中?还是每个对象都会保留自己的副本?这两种方法之间的根本区别是什么?哪个最适合哪种情况?
var Employee = function (name) {
this.name = name;
};
Employee.prototype.print = function () {
console.log(this.name);
}
var emp1 = new Employee("jack"),
emp2 = new Employee("mark");
emp1.print();
emp2.print();
var EmployeeNew = {
init: function (name) { this.name = name; },
print: function () {
console.log(this.name);
}
};
var empNew1 = Object.create(EmployeeNew),
empNew2 = Object.create(EmployeeNew)
empNew1.init("jack")
empNew1.print();
empNew2.init("jack");
empNew2.print();
最佳答案
您的两个代码示例通常是等价的(除了一些与问题无关的次要细节)。
这...
Object.create(EmployeeNew)
...创建一个以 EmployeeNew
对象为原型(prototype)的新对象。所以 print
和 init
函数是共享的。
console.log(empNew1.init === empNew2.init); // true
console.log(empNew1.print === empNew2.print); // true
为了进一步说明,这是一个采用以下步骤的示例...
- 创建一个
EmployeeNew
对象以供Object.create
使用 - 使用
Object.create
创建 2 个独特的对象 - 验证新对象是否可以使用
EmployeeNew
提供的功能 - 向
EmployeeNew
添加一个新函数 - 查看第 2 步中的对象是否可以使用该新功能
第 1 步:创建一个 EmployeeNew
对象
var EmployeeNew = {
init: function (name) { this.name = name; },
print: function () {
console.log(this.name);
}
};
第 2 步:使用 Object.create
var empNew1 = Object.create(EmployeeNew),
empNew2 = Object.create(EmployeeNew)
第 3 步:验证新对象是否可以使用 EmployeeNew
empNew1.init("jack");
empNew1.print();
empNew2.init("jack");
empNew2.print();
第 4 步:向 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)
。
简单来说,当我们查找一个属性时,例如在 empNew1
上,如果 empNew1
没有该属性,它会自动查找它的prototype 以查看该对象上是否存在该属性。如果是,它会使用它。
关于您的评论...
"...suppose, if create this.name as property ( name : "") is the name property also will be treated as prototype..."
是的,如果我们这样做...
EmployeeNew.name = "unknown"
...然后该属性将在所有以 EmployeeNew
作为其原型(prototype)对象的实例之间共享。
但是
因为原型(prototype)上的 .name
属性是一个不可变的原始值(一个字符串),如果我们尝试写入该属性, .name
属性自动直接添加到实例中。
继续上面的例子...
EmployeeNew.name = "unknown";
现在之前创建的实例将引用该属性...
empNew1.name; // "unknown"
empNew2.name; // "unknown"
...但是现在让我们更新一个实例的属性...
empNew1.name = "bubba";
empNew1.name; // "bubba"
empNew2.name; // "unknown"
这是因为 empNew1
现在有自己的 .name
属性引用 "bubba"
。这隐藏empNew1
原型(prototype)上的.name
属性,因此对该属性的搜索永远不会扩展到原型(prototype)对象中。
由于 empNew2
没有被分配 .name
,它仍然会在其原型(prototype)中查找该属性。
关于javascript - 原型(prototype)函数和json符号函数的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10128837/