了解使用 'Object.create()' 而不是 'new' 关键字创建原型对象
Understanding prototype object creation with 'Object.create()' instead of 'new' keyword
我找到了包含这些行的代码
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.create
和 new
有什么区别?
这两行是 Metadata
扩展 Backend
.
的典型方式
类 in JavaScript 定义为函数。如果在函数上定义 prototype
,则可以使用 new
关键字(或 Object.create
)创建 class 的实例。原型上的 functions/properties 将位于您创建的 class 的新实例上。
在上面的代码中,Metadata.prototype
被设置为 Backend
的实例,因此 Metadata.prototype
将继承调用 Backend.prototype
上的 methods/properties。
您可以在 Inheritance and the prototype chain 找到更多信息。
在 JavaScript 中没有 类,取而代之的是我们可以使用 new
关键字调用构造函数来创建新对象,因此我们将获得与类 和实例化。
而这两行是用来表示继承,让Metadata
extends Backend
,在行中:
Metadata.prototype = Object.create(Backend.prototype);
我们定义Metadata
对象的原型,应该是新建对象的原型。
在这一行中:
Metadata.prototype.constructor = Metadata;
我们定义 Metadata
的构造函数,它将用于创建 Metadata
的新实例。
继承可以这样测试:
var meta = new Metadata();
console.log('Is meta an instance of Metadata? ' + (meta instanceof Metadata)); // true
console.log('Is meta an instance of Backend? ' + (meta instanceof Backend)); // true
您可以在此处 Object.create() documentaion 中的另一个示例中找到更多相关信息。
Object.create
是一个ES6方法,它以给定的对象为原型创建一个对象。
Metadata.prototype = Object.create(Backend.prototype);
所以上面一行的意思是Metadata
继承了Backend
的所有属性和方法。它有点类似于 ES6 之前的以下行:
Metadata.prototype = new Backend();
然而,Metadata
也继承了 constructor
属性 来自 Backend
:
var metaData = new Metadata();
metaData.constructor; // function Backend()
这看起来很奇怪,因为 metaData
实际上是用 Metadata
构造的,所以我们这样修复它:
Metadata.prototype.constructor = Metadata;
var metaData = new Metadata();
metaData.constructor; // function Metadata()
请注意,这不会与 instanceof
运算符混淆:
metaData instanceof Metadata // true
metaData instanceof Backend // true
JavaScript 是一种基于原型的语言。
这意味着它不像其他语言那样使用 class 关键字。相反 JavaScript 使用 函数 作为 classes.
在您的示例中, data 变量可以同化为 class:
var Data = function() { ... }
要创建此 class 的实例,我们使用 new 关键字将类型对象的结果分配给变量.
var data = new Data()
自 ECMA Script 6 以来,我们可以使用实例化方法 Object.create()
来创建具有指定原型对象和属性的未初始化对象。它接受参数对象,该对象应该是新创建对象的原型。 (它也复制构造函数)
因此,以下几行是使元数据扩展后端对象并保留其自己的构造函数的方法:
// 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>
我找到了包含这些行的代码
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.create
和 new
有什么区别?
这两行是 Metadata
扩展 Backend
.
类 in JavaScript 定义为函数。如果在函数上定义 prototype
,则可以使用 new
关键字(或 Object.create
)创建 class 的实例。原型上的 functions/properties 将位于您创建的 class 的新实例上。
在上面的代码中,Metadata.prototype
被设置为 Backend
的实例,因此 Metadata.prototype
将继承调用 Backend.prototype
上的 methods/properties。
您可以在 Inheritance and the prototype chain 找到更多信息。
在 JavaScript 中没有 类,取而代之的是我们可以使用 new
关键字调用构造函数来创建新对象,因此我们将获得与类 和实例化。
而这两行是用来表示继承,让Metadata
extends Backend
,在行中:
Metadata.prototype = Object.create(Backend.prototype);
我们定义Metadata
对象的原型,应该是新建对象的原型。
在这一行中:
Metadata.prototype.constructor = Metadata;
我们定义 Metadata
的构造函数,它将用于创建 Metadata
的新实例。
继承可以这样测试:
var meta = new Metadata();
console.log('Is meta an instance of Metadata? ' + (meta instanceof Metadata)); // true
console.log('Is meta an instance of Backend? ' + (meta instanceof Backend)); // true
您可以在此处 Object.create() documentaion 中的另一个示例中找到更多相关信息。
Object.create
是一个ES6方法,它以给定的对象为原型创建一个对象。
Metadata.prototype = Object.create(Backend.prototype);
所以上面一行的意思是Metadata
继承了Backend
的所有属性和方法。它有点类似于 ES6 之前的以下行:
Metadata.prototype = new Backend();
然而,Metadata
也继承了 constructor
属性 来自 Backend
:
var metaData = new Metadata();
metaData.constructor; // function Backend()
这看起来很奇怪,因为 metaData
实际上是用 Metadata
构造的,所以我们这样修复它:
Metadata.prototype.constructor = Metadata;
var metaData = new Metadata();
metaData.constructor; // function Metadata()
请注意,这不会与 instanceof
运算符混淆:
metaData instanceof Metadata // true
metaData instanceof Backend // true
JavaScript 是一种基于原型的语言。
这意味着它不像其他语言那样使用 class 关键字。相反 JavaScript 使用 函数 作为 classes.
在您的示例中, data 变量可以同化为 class:
var Data = function() { ... }
要创建此 class 的实例,我们使用 new 关键字将类型对象的结果分配给变量.
var data = new Data()
自 ECMA Script 6 以来,我们可以使用实例化方法 Object.create()
来创建具有指定原型对象和属性的未初始化对象。它接受参数对象,该对象应该是新创建对象的原型。 (它也复制构造函数)
因此,以下几行是使元数据扩展后端对象并保留其自己的构造函数的方法:
// 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>