原型函数和 json 表示法函数之间的区别
Difference between prototype function and json notation function?
我在下面创建了两个员工类,一个使用构造函数,另一个使用JSON表示法。在构造函数中,print
函数是由原型创建的,因此只保留一个副本,对象(emp1
和emp2
)共享此print
函数。
问:在 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
对象作为其原型的新对象。因此,print
和init
功能是共享的。
console.log(empNew1.init === empNew2.init); // true
console.log(empNew1.print === empNew2.print); // true
为了进一步说明,下面是一个采用以下步骤的示例...
- 创建供
Object.create
使用的EmployeeNew
对象 - 使用
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
创建 2 个唯一对象
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
没有该属性,它会自动查看其原型以查看该属性是否存在于该对象上。如果是这样,它会使用它。
关于您的评论...
"...假设,如果创建 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
现在有自己的引用"bubba"
的.name
属性。这隐藏了empNew1
原型上的.name
属性,因此对该属性的搜索永远不会扩展到原型对象中。
由于empNew2
没有被分配.name
,它仍然会寻找该属性的原型。
这两种情况都是等效的,你只需要考虑什么对你的编码风格来说更直观,如果使用new及其所有初始参数创建新对象,或者使用init方法。
Class实现的一个优点是,如果你在 Class 定义中组合你的对象(我知道,它不像原型),你可以创建内部私有属性,而仅使用原型就不能(除非你使用特殊符号(如下划线前缀)标记它们)。最后只是一个风格问题,你觉得什么更舒服。
- Jquery在函数之间传递表行
- d3中堆栈函数和嵌套函数之间的差异
- 如何在函数之间切换
- JavaScript/jQuery-添加添加和删除类与下一个函数之间的延迟
- Javascript-defineProperty和直接在对象上定义函数之间的区别
- 在函数之间传递javascript变量
- 两个函数之间的角度承诺
- Javascript创建函数,以便在其他函数之间共享变量
- 直接绑定和使用每个函数之间的区别
- 节点模块对象范围:在所有函数之间共享一个对象
- js 函数之间使用参数的区别
- angularjs+ui.router:指令控制器和链接函数之间的不同行为
- 如何在onchange事件中的两个函数之间进行选择
- 在使用ajax调用的函数之间调用相同的函数
- 在JavaScript函数之间传递JSON值
- 试图理解JavaScript中原型和构造函数之间的区别
- 什么'新函数和函数之间的区别
- javascript函数之间的OR运算符
- 以下jquery和requireJS函数之间的区别
- 在Javascript中的函数之间共享变量