我来到一个包含这些行的代码
var data = function() { function Metadata() { /*some initialization here*/ } Metadata.prototype = Object.create(Backend.prototype); Metadata.prototype.constructor = Metadata; return Metadata; }
我很难理解实际发生了什么,以及如何使用返回的对象.如果我正确理解,数据现在将是一个应该像这样初始化的对象
var d = new data()
但是我不明白以下几行,为什么使用Object.create()而不是new关键字:
Metadata.prototype = Object.create(Backend.prototype); Metadata.prototype.constructor = Metadata;
他们在做什么?有必要吗Object.create和new之间有什么区别?
解决方法
JavaScript是一种基于原型的语言.
这意味着它不像其他语言那样使用class关键字.相反,JavaScript将函数用作类.
在你的例子中,数据变量可以被同化到一个类中:
这意味着它不像其他语言那样使用class关键字.相反,JavaScript将函数用作类.
在你的例子中,数据变量可以被同化到一个类中:
var Data = function(){…}
要创建这个类的一个实例,我们使用new关键字将类型object的结果分配给一个变量.
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;
实际上两者非常相似,主要区别在于新的关键字实际上是运行构造函数代码,而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>