javascript - 原型(prototype)函数和json符号函数的区别?

标签 javascript json prototype javascript-objects object-literal

我在下面创建了两个员工类,一个使用构造函数,另一个使用 JSON 表示法。在构造函数中,print 函数是由原型(prototype)创建的,因此只会保留一个副本,对象(emp1emp2)共享此 打印功能。

问题:在 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)的新对象。所以 printinit 函数是共享的。

console.log(empNew1.init === empNew2.init); // true
console.log(empNew1.print === empNew2.print); // true

为了进一步说明,这是一个采用以下步骤的示例...

  1. 创建一个 EmployeeNew 对象以供 Object.create 使用
  2. 使用 Object.create 创建 2 个独特的对象
  3. 验证新对象是否可以使用EmployeeNew提供的功能
  4. EmployeeNew 添加一个新函数
  5. 查看第 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'

因此您可以看到 empNew1empNew2 能够观察到 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/

相关文章:

json - 如何为 GeoShape Circle 创建 JSON-LD 架构?

javascript - 调用 javascript 原型(prototype)方法时未定义的函数

typescript - 用 typescript 定义原型(prototype)函数

javascript - 动态创建元素后的 jQuery 选择器

javascript - d3 v4 : How to make a path being curved when only start and end point are known?

javascript - 如何在数组中使用reduce方法将具有公共(public)键的多个Json对象转换为单个Json对象?

javascript - 创建 jquery 菜单 - json 响应

javascript - 图片加载后隐藏加载动画

json - Groovy 中的动态类型类型

JavaScript:复制对象键值而不更改引用的对象键