javascript - 了解使用 'Object.create()' 而不是 'new' 关键字创建原型(prototype)对象

标签 javascript object constructor prototype

我找到了包含这些行的代码

var data = function() {
    function Metadata() { /*some initialization here*/ }

    Metadata.prototype = Object.create(Backend.prototype);
    Metadata.prototype.constructor = Metadata;

    return Metadata;
}

我很难理解到底发生了什么,以及如何使用返回的对象。如果我理解正确,data 现在将是一个应该像这样初始化的对象

var d = new data()

但我不明白以下几行以及为什么使用 Object.create() 而不是 new 关键字:

Metadata.prototype = Object.create(Backend.prototype);
Metadata.prototype.constructor = Metadata;

他们是做什么的?它们有必要吗? Object.createnew 有什么区别?

最佳答案

JavaScript 是一种基于原型(prototype)的语言。 这意味着它不像其他语言那样使用 class 关键字。相反,JavaScript 使用函数 作为类。
在您的示例中,data 变量可以同化为一个:

var Data = function() { ... }

要创建此类的实例,我们使用 new 关键字将类型对象的结果分配给变量。

var data = new Data()

从 ECMA Script 6 开始,我们可以使用实例化方法 Object.create() 来创建具有指定原型(prototype)对象和属性的未初始化对象。它接受参数对象,该对象应该是新创建对象的原型(prototype)。 (它也复制了构造函数)

因此,以下几行是使 Metadata 扩展 Backend 对象并保留其自己的构造函数的方法:

// Metadata extends Backend
Metadata.prototype = Object.create(Backend.prototype);
Metadata.prototype.constructor = Metadata;

但这段代码并不完全等同于 Metadata.prototype = new Backend();。看这个例子:

//Base class
var Backend = function(){ this.publicProperty='SomeValue'; }

//Extension class 1
var Metadata1 = function() { }
Metadata1.prototype = Object.create(Backend.prototype);
Metadata1.prototype.constructor = Metadata1;

//Extension class 2
var Metadata2 = function() { }
Metadata2.prototype = new Backend();


/*
 *  Then the results are different (see code snippet at the end of this post)
 */
//result1 = 'undefined'
var data1 = new Metadata1();
var result1 = data1.publicProperty;

//result2 = 'SomeValue'
var data2 = new Metadata2();
var result2 = data2.publicProperty;

其实两者非常相似,主要区别在于new关键字实际运行构造函数代码,而Object.create不会执行代码。

另一个区别是使用 Object.create 您可以创建一个不继承任何对象的对象 (Object.create(null))。
而如果您执行 Metadata.prototype = null,新创建的对象将继承自 Object.prototype


注意:在一些较旧的浏览器(IE8 及以下)中,您可以使用此等效代码来Object.create:

Object.create = function(o){
    function F(){}
    F.prototype=o;
    return new F();
}

这是显示两种方法之间差异的工作代码片段

//Base class
var Backend = function(){ this.publicProperty='SomeValue'; }

//Extension class 1
var Metadata1 = function() { }
Metadata1.prototype = Object.create(Backend.prototype);
Metadata1.prototype.constructor = Metadata1;

//Extension class 2
var Metadata2 = function() { }
Metadata2.prototype = new Backend();


//result: 'undefined'
var data1 = new Metadata1();
$("#result1").text("result1: " +  (typeof data1.publicProperty=='undefined' ? 'undefined' : data1.publicProperty));

//result: 'SomeValue'
var data2 = new Metadata2();
$("#result2").text("result2: " +  (typeof data2.publicProperty=='undefined' ? 'undefined' : data2.publicProperty));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result1"></div>
<div id="result2"></div>

关于javascript - 了解使用 'Object.create()' 而不是 'new' 关键字创建原型(prototype)对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30512776/

相关文章:

javascript - Sequelize - 按降序获取值

c++ - 使用默认构造函数初始化变量

javascript - 是否可以将构造函数作为类中的方法?

JavaScript myObject 有时未定义

java - 将参数传递给 java android 类

javascript - 以 Angular 创建嵌套的动态组件

javascript - 如何更改 fullCalendar 中类型的事件背景颜色?

javascript - Jquery 附加到标签

python - Blender Python API 添加属性到对象

javascript - angularjs 将 json 对象转换为数组