明確にするために、JSはクラスを認識せず、オブジェクトとカスタムの自己定義コンストラクター関数のみを認識しますが、それは重要なことではありません。
簡単に言うと、あなたの質問に答えるには、そうです。ここに投稿する新しいオブジェクトを作成するさまざまな方法の間には、いくつかの小さな違いがあり、かなり大きな違いさえあります。
CoffeeScript:
これは実際には、独自のコンストラクターを作成するための最も明確で従来の方法ですが、(オプションの)クロージャー変数を使用するようにセットアップできるという意味で「最適化」されています。
基本的に、このコードが行うことは、IIFEを使用して、コンストラクター定義とproptotypeメソッドの割り当ての両方を、新しいコンストラクターへの参照を返す独自のプライベートスコープでラップすることです。クリーンでシンプルなJSであり、自分で書いたものと何ら変わりはありません。
ノックアウト:
少なくとも、あなたが提供するスニペットは、モジュールパターンの一部か、パワーコンストラクターのように見えるので、これは私を少し投げました。ただし、を使用していないためstrict mode
、を省略しても危険な状況になります。また、関数全体がの新しいインスタンスをnew
作成する手間を省くため、2番目のオブジェクトリテラルを作成し、その2番目のオブジェクトにすべてのプロパティを割り当てます。 、何かが足りないと思います。なぜなら、ここで最後のステートメントを省略しても、おそらくまったく違いはないでしょう。さらに、ご覧のとおり、本質的にコンストラクターであるメソッド()を宣言しています。これは、DifferentAnimal
DifferentAnimal
return {};
move
move
インスタンスには、プロトタイプから取得するのではなく、独自の関数オブジェクトが割り当てられます。
要するに、このスニペットをどこから入手したかをもう一度詳しく見て、これがフルバージョンであるかどうかを再確認してください。フルバージョンの場合は、これに対する議論しか見ることができないためです。
コンストラクター内で定義された変数の使用は単純です。クロージャ。プロパティが、いくつかの引数によって決定され、そのコンストラクターに渡される明確な初期状態を持っていると仮定します。
function MyConstructor(param)
{
var paramInit = param/2;//or something
this.p = paramInit;//this property can change later on, so:
this.reInit = function()
{//this method HAS to be inside constructor, every instance needs its own method
this.p = paramInit;//var paramInit can't, it's local to this scope
};
}
var foo = new MyConstructor(10);
console.log(foo.p);//5
foo.p = 'hi';
console.log(foo.p);//hi
foo.reInit();
console.log(foo.p);//5
console.log(foo.paramInit);//undefined, not available outside object: it's a pseudo-private property
本当にそれだけです。pplが何かを使用しているのを見ると、それは多くの場合、 (参照とは何ですか? 1つ以外のオブジェクトに適用されたときにメソッドは何をすべきか)var that = this;
の頭痛の種に対処することなく、どこでも利用できるメインオブジェクトへの参照を作成することですもともとは?etceteraを対象としていました...)this
this
バックボーン:
ここでは、別のケースを扱っています。オブジェクトの拡張(つまり、メソッドの使用、既存の「クラス」(コンストラクター)または特定のインスタンスのプロパティ)は、単にオブジェクトを作成することと同じではありません。
ご存知のように、JSオブジェクトにはいつでも新しいプロパティを割り当てることができます。これらのプロパティも削除できます。場合によっては、プロトタイプのプロパティをインスタンス自体で再定義できます(プロトタイプの動作をマスクします)など。したがって、結果のオブジェクト(指定されたインスタンスを拡張する新しく作成されたオブジェクト)をどのように表示するかによって異なります。インスタンスからすべてのプロパティを取得する必要がありますか、それとも両方のオブジェクトが将来的に同じプロトタイプを使用するようにしますか?
これらは両方とも単純なJSを使用して実現できますが、自分で作成するにはもう少し手間がかかります。ただし、次のように書くと、次のようになります。
function Animal(name)
{
this.name = name;
}
Animal.prototype.eat= function()
{
console.log(this.name + ' is eating');
};
これは、書くことと同等と見なすことができます。
var Animal = Object.extend({name:'',eat:function()
{
console.log(this.name + ' is eating');
}});
はるかに短いですが、コンストラクターがありません。
new
vsObject.create
ええと、それは簡単なことです。Object.create
それははるかに強力ですnew
。代わりに、オブジェクトを作成する必要があるときに、プロトタイプのメソッド、プロパティ(天気を含む、列挙可能かどうかなど)を定義できます。コンストラクターとプロトタイプを作成するか、オブジェクトリテラルを作成して、これらすべてのObject.defineProperty
行をいじくりまわす必要があります。
欠点:まだ一部の人々ECMA5準拠のブラウザーを使用していません(IE8はまだ完全に機能していません)。私の経験では、しばらくするとかなりのスクリプトをデバッグするのが非常に難しくなります。通常のコンストラクターよりもパワーコンストラクターを使用する傾向がありますが、スクリプトの最上部に明確で明確な定義があります。非常にわかりやすい名前ですが、オブジェクトリテラルは私が「オンザフライ」で作成するものです。を使用してObject.create
、オブジェクトリテラルであるかのように、実際のオブジェクトリテラルとして認定するには実際には少し複雑すぎるオブジェクトを作成する傾向があることに気付きました。
//fictional example, old:
var createSomething = (function()
{
var internalMethod = function()
{//method for new object
console.log(this.myProperty || '');
};
return function(basedOn)
{
var prop, returnVal= {};
returnVal.myProperty = new Date();
returnVal.getCreated = internalMethod;//<--shared by all instances, thx to closure
if (!basedOn || !(basedOn instanceof Object))
{//no argument, or argument is not an object:
return returnVal;
}
for (prop in basedOn)
{//extend instance, passed as argument
if (basedOn.hasOwnProperty(prop) && prop !== '_extends')
{
returnVal[prop] = basedOn[prop];
}
}
returnVal._extends = basedOn;//<-- ref as sort-of-prototype
return returnVal;
};
}());
これはかなり冗長ですが、基本的なコンストラクターを用意しました。これを使用して、既存のインスタンスを拡張することもできます。単純に書くのはそれほど冗長ではないように思われるかもしれません。
var createSomething = Object.create(someObject, {getCreated:function()
{
console.log(this.myProperty);
},
myProperty:new Date()});
しかし、IMOの場合、これにより、どのオブジェクトがどこで作成されたかを追跡することが難しくなります(主にObject.create
式であり、持ち上げられないためです。
もちろん、決定的な議論にはほど遠いです。どちらにも長所と短所があります。モジュールパターン、クロージャ、パワーコンストラクタを使用することをお勧めします。そうでない場合は問題ありません。
これがあなたのために1つか2つをクリアしたことを願っています。