我一直在阅读很多关于javascript中"继承"的文章.其中一些使用,new而其他人推荐Object.Create.我读的越多,我就越困惑,因为它似乎存在无穷无尽的变体来解决继承问题.
有人可以向我展示最受欢迎的方式(如果有的话,还是事实上的标准)?
(我想有一个基础物体Model,我可以延伸RestModel或LocalStorageModel).
Ber*_*rgi 11
简单:Object.create在所有环境中都不受支持,但可以使用new.除此之外,两者有不同的目的:Object.create只创建一个继承自其他的Object,同时也调用构造函数.使用适当的.new
在你的情况下,你似乎希望RestModel.prototype继承自Model.prototype.Object.create(或其shim)是正确的方法,因为你不想a)创建一个新实例(实例化a new Model)和b)不想调用Model构造函数:
RestModel.prototype = Object.create(Model.prototype);
Run Code Online (Sandbox Code Playgroud)
如果要在RestModels上调用Model构造函数,则与原型无关.使用call()或apply()为此:
function RestModel() {
Model.call(this); // apply Model's constructor on the new object
...
}
Run Code Online (Sandbox Code Playgroud)
ZER*_*ER0 11
JavaScript是一种基于原型而不是类的OOP语言.这是你可以看到的所有这些混乱的原因之一:许多开发人员使用JS,因为它是基于类的.
因此,您可以看到许多库试图在JS中使用基于类的语言范例.
此外,JS本身缺乏一些特性,这些特性使得继承,也是基于原型的,痛苦的.例如,在Object.create没有办法从另一个对象创建对象之前(作为基于OOP原型的语言应该这样做),但只使用functionas构造函数.
而且也是因为这个原因,你可以看到很多图书馆试图以自己的方式"修复"语言.
所以,你的困惑是正常的.比方说,"官方"方式是使用prototype属性,functions作为构造函数,并Object.create从对象的insteance创建.然而,如上所述,在某些情况下,代码是冗长的或缺乏功能,因此这个过程通常以某种方式包装,然后它成为个人品味的问题.
因为你在谈论模型,你可以看看Backbone的模型,看看这种方法是否适合你.
更新:举一些例子我希望能帮助你澄清一下,这里使用的旧学校继承方式new:
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();
Run Code Online (Sandbox Code Playgroud)
现在,这里的问题:
Model只有在RestModel.prototype设置时才会调用构造函数一次.因此,foo每个RestModel实例的属性都是"foo".RestModel实例都将共享this.array属性中相同数组的相同实例.如果Model直接创建实例,则每个实例都有一个新的数组实例.myModel.constructor是Model不是RestModel.那是因为我们prototype用一个新的实例覆盖Model,包含constructor等于Model.RestModel对构造函数进行惰性调用的新实例,那是不可能的.我认为有一些要点,当然它们不是唯一的.那么,如何解决这个问题呢?正如我所说,很多人已经这样做了,他们创建了库和框架也限制了冗长.但是,有一个想法:
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);
Run Code Online (Sandbox Code Playgroud)
请注意,如果您不想使用prototype或function作为构造函数,Object.create您可以这样做:
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);
Run Code Online (Sandbox Code Playgroud)
要么:
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();
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您基本上模仿构造函数.您也可以传递descriptor给Object.create(参见文档),但它变得更加冗长.大多数人使用某种extend功能或方法(正如您在Backbone示例中看到的那样).
希望能帮助到你!
| 归档时间: |
|
| 查看次数: |
2841 次 |
| 最近记录: |