ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript_js オブジェクト指向でクラスとオブジェクトを定義するいくつかの方法

JavaScript_js オブジェクト指向でクラスとオブジェクトを定義するいくつかの方法

WBOY
WBOYオリジナル
2016-05-16 18:16:46950ブラウズ

この例を見てみましょう:

コードをコピーします コードは次のとおりです:

var a = 'グローバル' ;
(関数 () {
alert(a);
var a = 'ローカル';
})(); >
皆さん、まずはこの例を見て、出力は何だと思いますか? 'グローバル'?それとも「地元」?実際、そうではありません。出力は未定義です。これについて話したいだけです。
実際、JavaScript の動作メカニズムを見てみると、それは非常に簡単です。この現象は「ステートメント前」と考えることができます。しかし、もう少し深く掘り下げてみると、より明確に理解できるようになります。
これには実際にはオブジェクト プロパティ バインディング メカニズムが関係します。すべての JavaScript 関数はオブジェクトであるためです。関数内で宣言された変数は、このオブジェクトの「類似のプロパティ」と見なすことができます。オブジェクトのプロパティのバインディングは、言語では「アーリー バインディング」と「レイト バインディング」に分けられます。

[初期バインディング]
は、オブジェクトをインスタンス化する前にオブジェクトのプロパティとメソッドを定義することを指します。プログラムを解析するときに、事前にマシンコードに変換できます。 C や Java などの一般的な型付け言語はすべて、早期バインディング メカニズムを使用します。また、JavaScript は厳密に型指定された言語ではありません。 「遅延バインディング」メカニズムを使用します。
【Late Binding】
は、プログラムを実行する前にオブジェクトの種類を確認する必要はなく、オブジェクトがプロパティとメソッドをサポートしているかどうかだけを確認することを意味します。バインド前に、ペナルティなしでオブジェクトに対して多数の操作を実行できます。
上記のコードの「事前宣言」現象は、「遅延バインディング」メカニズムによって説明できます。関数のスコープ内では、すべての変数は「遅延バインド」されます。 つまり、ステートメントはトップレベルです。したがって、上記のコードは次のコードと一致しています:



コードをコピーします コードは次のとおりです: var a = 'グローバル';
(function () {
var a;
alert(a);
a = 'ローカル';
})(); >

alert(a) の前には、値を代入せずに a だけが宣言されていました。したがって、結果は想像できます。

RT: この記事で説明するのは、JavaScript でクラスとオブジェクトを定義するいくつかの方法です。 - ステートメント: 以下の内容のほとんどは「JavaScript Advanced Programming」から来ていますが、個人的な説明方法は異なります -- >
【直接量法】
オブジェクトを構築するために直接量を使用するのが最も基本的な方法です。しかし、デメリットもたくさんあります。




コードをコピーします
コードは次のとおりです。 var Obj = new Object; Obj.name = 'sun'; Obj.showName = function() { alert('this.name');
}


オブジェクト Obj を構築します。これには属性名とメソッド showName があります。しかし、別の同様のオブジェクトを構築したい場合はどうすればよいでしょうか?もう一度繰り返さなければなりませんか?
いいえ! 、特定の型のオブジェクトを返すファクトリ関数を使用して実装できます。工場と同じように、パイプラインは必要な特定の種類の結果を出力します。
【ファクトリメソッド】



コードをコピー

コードは次のとおりです。 function createObj (名前) { var tempObj = 新しいオブジェクト; tempObj.showName = 関数 () { alert(this.name); >return tempObj ;
}
var obj1 = createObj('obj_one');


多くの人はこれを使用しませんファクトリー関数 オブジェクトを構築する形式として。理由の 1 つはセマンティクスです。演算子 new を使用して構築するほど形式的ではありません。もう 1 つ大きな理由があります。このファクトリはオブジェクトを生成するたびに新しい関数 showName() を作成するためです。つまり、各オブジェクトのバージョンは異なりますが、実際には同じ関数を共有します。
ファクトリ関数の外で showName を定義し、属性を通じてメソッドを指す人もいます。これにより、この問題を回避できます。




コードをコピー

コードは次のとおりです。


function showName () {
alert(this.name); } function createObj(name) { var tempObj = 新しいオブジェクト ; tempObj.showName = showName; var obj1 = createObj('obj_one'); obj2 = createObj( 'obj_two');
残念ながら、このメソッドでは showName() 関数がオブジェクトのメソッドのように見えません。
[コンストラクターメソッド]
このメソッドは、上記のファクトリー関数の最初の問題、つまり新しい演算子が存在しない問題を解決するものです。しかし、それでも 2 番目の問題は解決できません。見てみましょう。
コードをコピーします コードは次のとおりです。

function Obj(name) {
this.name = 名前;
this.showName = function () {
alert(this.name);
}
var obj('obj_one'); 🎜>var obj2 = new Obj('obj_two');


利点は、new 演算子が自動的にオブジェクトを作成するため、コンストラクターで新しいオブジェクトを作成する必要がないことです。が実行され、これを介してのみこのオブジェクトにアクセスします。したがって、 this を通じてこのオブジェクトに直接値を割り当てることができます。また、これはデフォルトでコンストラクターの戻り値を指すため、return する必要はありません。
同時に、新しいキーワードを使用して必要なオブジェクトを作成すると、より「正式」に感じられます。
残念ながら、ファクトリ関数と同様にメソッド関数を繰り返し生成する問題はまだ解決できません。

[プロトタイプ手法]
この手法は、上記の手法と比較して、メソッド関数が複数回生成される問題を解決できるという大きな利点があります。オブジェクトのプロトタイプ プロパティを利用します。オブジェクト インスタンスをオーバーライドするにはプロトタイプに依存します。


var Obj = function () {}
Obj .prototype.name = 'me';
Obj.prototype.showName = function () {
alert(this.name);
var obj1 = new Obj();
var obj2 = new Obj();


プロトタイプに依存してコンストラクターを書き換えます。そのため、プロパティとメソッドは両方ともプロトタイプ参照を通じて与えられます。一度作成されました。残念ながら、この方法には 2 つの致命的な問題があります。
1.プロトタイプはコンストラクターのスコープ外にあるため、オブジェクトの構築時に必要なプロパティを記述する方法はありません。また、パラメーターを渡してオブジェクトを作成するときにプロパティ値を記述する方法はありません。値は、オブジェクトの作成後にのみオーバーライドできます。
2.致命的な問題は、プロパティがオブジェクトを指す場合、そのオブジェクトが複数のインスタンスで共有されることです。次のコードを考えてみましょう:



コードをコピー コードは次のとおりです: var Obj = function () { }
Obj.prototype.name = 'me';
Obj.prototype.flag = new Array('A', 'B');
Obj.prototype.showName = function () {
alert(this.name);
}
var obj1 = new Obj();
var obj2 = new Obj('C') ;
alert(obj1.flag); // A,B,C
alert(obj2.flag); //A,B,C


フラグ属性の場合object をポイントしている場合、obj1 と obj2 の両方のインスタンスがそれを共有します。obj1 の flag 属性のみを変更した場合でも、その変更はインスタンス obj2 に表示されます。
この問題に直面して、[コンストラクター メソッド] と [プロトタイプ メソッド] を組み合わせて補完する必要があるかどうかを考えなければなりません。 。 。
[コンストラクターとプロトタイプの混合メソッド]
コンストラクター メソッドを使用してプロパティを作成できるようにし、プロトタイプ メソッドを使用してメソッドを作成できます:




コードをコピー
コードは次のとおりです。 var Obj = function (name) { this.name = name; .flag = new Array(' A', 'B');
}
Obj.prototype = {
showName : function () {
alert(this.name);
}
var obj1 = new Obj();
var obj2 = new Obj();
obj1.flag.push('C'); // A,B,C
alert(obj2.flag); //A,B


このメソッドは、プロトタイプとコンストラクターの利点を効果的に組み合わせたもので、現在最も使用されているメソッドです。副作用が最も少ないです。
しかし、完璧を追求する人の中には、視覚的にまだ要件を満たしていないため、まだ満足していない人もいます。プロトタイプを介してメソッドを作成するプロセスは、依然として視覚的に人々にインスタンス メソッドのように見えないと感じさせるためです (特に、 )
したがって、プロトタイプをアクティブにし、それをコンストラクターに追加して、コンストラクターをより視覚的に統合することができます。この一連の処理は一度の判断だけで完了します。



コードをコピー


コードは次のとおりです:

var Obj = function (name) {
this.name = name;
this.flag = new Array('A', 'B'); _init == '未定義') {
Obj.prototype = {
showName : function () {
alert(this.name)
}
}; = true;
}
}


上記と同様に、_init をフラグとして使用して、プロトタイプに対してメソッドが作成されたかどうかを判断します。その場合、実行されません。実際、メソッドは依然としてプロトタイプを通じて作成されており、本質的には変わりません。唯一の違いは、このコンストラクターが「統一」されているように見えることです。
ただし、この動的プロトタイピング方法には問題があり、「JavaScript 高度なプログラミング」では詳しく説明されていません。最初のオブジェクトを作成するとき、オブジェクトがインスタンス化される前にプロトタイプが構築されないため、オブジェクトにはまったくアクセスできません。したがって、最初のオブジェクトはプロトタイプ メソッドにアクセスできません。同時に、この方法ではサブクラスの継承にも問題が発生します。
次の記事で解決策を説明します。

実際、使いやすさという点では、個人的にはこのように判断する必要はないと感じています。 。 。笑 ^_^
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。