new
,而其他一些则建议使用Object.Create
。我读得越多,我就越困惑,因为它似乎存在无穷无尽的变种来解决继承问题。有人可以向我展示最可接受的方式吗(如果有的话,是事实上的标准)一个)?
(我想要一个基础对象
Model
,可以扩展RestModel
或LocalStorageModel
。)#1 楼
简单:并非在所有环境中都支持Object.create
,但可以使用new
进行填充。除此之外,两者有不同的目的:Object.create
只是创建一个从其他对象继承的对象,而new
也调用构造函数。使用适当的方法。在您的情况下,您似乎希望
RestModel.prototype
继承自Model.prototype
。 Object.create
(或其垫片)是正确的方法,因为您不想a)创建一个新实例(实例化new Model
),b)不想调用Model构造函数:RestModel.prototype = Object.create(Model.prototype);
如果要在RestModels上调用Model构造函数,则与原型无关。使用
call()
或apply()
来实现以下目的:function RestModel() {
Model.call(this); // apply Model's constructor on the new object
...
}
#2 楼
JavaScript是一种基于原型而非类的OOP语言。这就是引起这种混乱的原因之一:许多开发人员都使用JS,因为它是基于类的。因此,您可以看到很多试图使用的库。
此外,JS本身缺乏使继承(也基于原型)痛苦的某些特征。例如,在
Object.create
之前,没有一种方法可以从另一个对象创建对象(就像基于OOP的基于原型的语言一样),而只能使用function
作为构造函数。原因,您会看到很多试图以自己的方式“修复”该语言的库。
所以,您的困惑很正常。说,“官方”方式是使用
prototype
属性,function
s作为构造函数,以及Object.create
从对象的实例创建。但是,如上所述,在某些情况下,代码很冗长或缺少功能,因此此过程通常以某种方式进行包装,然后成为个人喜好问题。因为您在说关于模型,您可以看看Backbone的模型,看看这种方法是否适合您。
function Model() {
this.foo = "foo";
this.array = [];
}
Model.prototype.foo = "";
Model.prototype.array = null;
Model.prototype.doNothing = function() {};
function RestModel() {
this.bar = "bar";
}
RestModel.prototype = new Model;
RestModel.prototype.bar = ""
var myModel = new RestModel();
现在,这里的问题是:仅在设置
new
时,一次调用Model
的构造函数。因此,每个RestModel.prototype
实例的foo
属性将为“ foo”。 不仅如此,所有
RestModel
实例还将在RestModel
属性中共享同一阵列的同一实例。如果直接创建this.array
的实例,则每个实例都有一个新的array实例。Model
是myModel.constructor
而不是Model
。这是因为我们用新的RestModel
实例覆盖了prototype
,其中包含Model
等于constructor
的新实例。如果您想通过延迟构造函数的方式来调用
Model
的新实例,那是不可能的。我认为有一些要点,当然,它们并不是唯一的要点。那么,该如何解决呢?正如我所说,很多人已经这样做了,他们创建了库和框架来限制冗长。但是,有一个想法:
function Model() {
this.foo = "foo";
this.array = [];
}
Model.prototype.foo = "";
Model.prototype.array = null;
Model.prototype.doNothing = function() {};
function RestModel() {
Model.call(this);
this.bar = "bar";
}
RestModel.prototype = Object.create(Model.prototype);
RestModel.prototype.constructor = RestModel;
RestModel.prototype.bar = ""
var myModel = new RestModel();
// for lazy constructor call
var anotherModel = Object.create(RestModel.prototype);
RestModel.call(anotherModel);
请注意,如果您不想使用
RestModel
或prototype
作为构造函数,则可以使用function
来做到这一点:var Model = {
foo: "",
array: null,
doNothing: function() {}
}
var RestModel = Object.create(Model);
RestModel.bar = "";
var myModel = Object.create(RestModel);
// Assuming you have to set some default values
initialize(RestModel);
或:
var Model = {
foo: "",
array: null,
doNothing: function() {},
init : function () {
this.foo = "foo";
this.array = [];
},
}
var RestModel = Object.create(Model);
RestModel.bar = "";
RestModel.init = function () {
Model.init.call(this);
this.bar = "bar";
}
var myModel = Object.create(RestModel);
myModel.init();
在这种情况下,您基本上模仿了构造函数。您还可以将
Object.create
传递给descriptor
(请参阅文档),但是它变得更加冗长。大多数人都使用某种Object.create
函数或方法(正如您可能在Backbone示例中看到的那样)。希望对您有所帮助!
评论
您建议我使用哪个示例?
– jgauffin
2012年6月5日17:34
所有这些都是有效的,但是以某种形式或另一种形式它们最终将变得冗长。例如,您可以对RestModel是否具有很多新的属性或方法进行成像。这就是我说JS仍然缺少某些东西时所说的。为了消除冗长,或者您决定使用第三方库,或者创建几个实用程序函数来执行此操作。我将避免使用纯粹的新方法(第一种),而只是决定第二种还是第三种,这取决于您是否对“类似于”“类”(第二种)(第三种)感到更舒服。
– ZER0
2012年6月5日17:49
评论
在这种情况下,为什么Object.Create比new更好?如果我也想支持构造函数怎么办?并且在RestModel和Model中都调用了该构造函数(如果我创建了RestModel)。我通常是C#开发人员,所以我并没有真正的区别。我想定义基本原型并使用构造函数,但我不明白如何同时获得两者?
– jgauffin
2012年6月5日14:11
我认为这个答案可以概括为“使用适当的内容”。有时您需要构造函数中的逻辑,有时则不需要。 +1
–user1106925
2012年6月5日14:13