私はjavascriptの「継承」に関する記事をたくさん読んでいます。それらのいくつかは使用しますがnew
、他は推奨しObject.Create
ます。継承を解決するためのバリアントが無限に存在するように見えるため、読むほど混乱します。
誰かが私に最も受け入れられている方法(または、ある場合は事実上の標準)を教えてくれませんか?
Model
(拡張できるベースオブジェクトが欲しい、RestModel
またはLocalStorageModel
。)
私はjavascriptの「継承」に関する記事をたくさん読んでいます。それらのいくつかは使用しますがnew
、他は推奨しObject.Create
ます。継承を解決するためのバリアントが無限に存在するように見えるため、読むほど混乱します。
誰かが私に最も受け入れられている方法(または、ある場合は事実上の標準)を教えてくれませんか?
Model
(拡張できるベースオブジェクトが欲しい、RestModel
またはLocalStorageModel
。)
シンプル:Object.create
すべての環境でサポートされているわけではありませんが、でシムすることができますnew
。それとは別に、この2つには異なる目的があります。Object.create
他のオブジェクトを継承するオブジェクトを作成するだけでなく、コンストラクター関数も呼び出します。適切なものを使用してください。new
あなたの場合、あなたはそれがRestModel.prototype
から継承することを望んでいるようですModel.prototype
。Object.create
(またはそのシム)が正しい方法です。これは、a)新しいインスタンスを作成(インスタンス化new Model
)し、b)モデルコンストラクターを呼び出したくないためです。
RestModel.prototype = Object.create(Model.prototype);
RestModelsでModelコンストラクターを呼び出したい場合、それはプロトタイプとは何の関係もありません。call()
またはそのためapply()
に:
function RestModel() {
Model.call(this); // apply Model's constructor on the new object
...
}
JavaScriptは、クラスではなくプロトタイプに基づくOOP言語です。これが、このような混乱の原因の1つです。多くの開発者は、クラスベースであるためJSを使用しています。
したがって、JSでクラスベース言語のパラダイムを使用しようとしている多くのライブラリを見ることができます。
さらに、JS自体には、継承をプロトタイプベースで苦痛にするいくつかの特性が欠けています。たとえば、以前Object.create
は(OOPプロトタイプベースの言語で行う必要があるように)別のオブジェクトからオブジェクトを作成する方法はありませんでしたが、function
コンストラクターとしてのみ使用していました。
また、そのため、言語を「修正」しようとしている多くのライブラリを、それぞれ独自の方法で見ることができます。
だから、あなたの混乱は正常です。たとえば、「公式」の方法は、コンストラクターとしてprototype
プロパティsを使用し、オブジェクトのインスタンスから作成することです。ただし、前述のように、コードが冗長であるか、機能が不足している場合があるため、この手順は何らかの形でラップされることが多く、個人的な好みの問題になります。function
Object.create
モデルについて話しているので、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();
さて、ここで問題があります:
Model
、が設定されている場合にのみ1回呼び出さ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);
コンストラクターとして使用したくない場合は、次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);
または:
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();
その場合、基本的にコンストラクターを模倣します。に渡すこともできますがdescriptor
(Object.create
ドキュメントを参照)、より冗長になります。ほとんどの人は、ある種のextend
関数またはメソッドを使用します(Backboneの例でおそらく見たように)。
それが役に立てば幸い!