ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScript コンストラクターとプロトタイプ オブジェクトの深い理解_JavaScript スキル

JavaScript コンストラクターとプロトタイプ オブジェクトの深い理解_JavaScript スキル

WBOY
リリース: 2016-05-16 16:35:50
オリジナル
1166 人が閲覧しました

一般的に使用されるいくつかのオブジェクト作成モード

新しいキーワードを使用して作成
オブジェクト作成の最も基本的な方法は、他のほとんどの言語とまったく同じです。オブジェクトは存在しないので、新しいオブジェクトを作成します。

var gf = new Object();
gf.name = "tangwei";
gf.bar = "c++";
gf.sayWhat = function() {
  console.log(this.name + "said:love you forever");
}
ログイン後にコピー

リテラルを使用して作成

これは適切だと思われますが、オタクは変数を定義するこのような複雑で控えめな方法を好むのでしょうか? スクリプト言語としては、他の言語と同じスタイルを持つ必要があるため、オブジェクト リテラルの定義方法が表示されました。 🎜>

var gf = {
  name : "tangwei",
  bar : "c++",
  sayWhat : function() {
    console.log(this.name + "said:love you forever");
  }
}
ログイン後にコピー

工場出荷時モード

実際、これはオブジェクトを定義するために実際に最も一般的に使用される方法ですが、類似したプロパティを持つオブジェクトを多数持ちたい場合はどうすればよいでしょうか (考えるのはとても楽しいです...)?それらを 1 つずつ定義すると、大量のコードが生成されることになるため、ファクトリを構築してオブジェクトをバッチで生成してみてはいかがでしょうか。したがって、JavaScript の世界初のインフレータブル ベイビーが誕生します。 。 。いいえ、「ファクトリーモデル」が誕生しました!

function createGf(name, bar) {
  var o = new Object();
  o.name = name;
  o.bar = bar;
  o.sayWhat = function() {
    alert(this.name + "said:love you forever");
  }
  return o;
}
var gf1 = createGf("bingbing","d");
var gf2 = createGf("mimi","a");
ログイン後にコピー

コンストラクター

ファクトリ パターンは、複数の同様のオブジェクトを作成する問題を解決しますが、これらのオブジェクトはすべてオブジェクトから作成されるという問題が再び発生します。現時点では、別のモード、コンストラクター モードに切り替える必要があります:

function Gf(name,bar){
  this.name = name;
  this.bar = bar;
  this.sayWhat = function(){
    alert(this.name + "said:love you forever");
  }
}
var gf1 = new Gf("vivian","f");
var gf2 = new Gf("vivian2","f");
ログイン後にコピー
ここでは、上の例の createGf を置き換えるために大文字で始まるコンストラクターを使用します。規則に従って、コンストラクターの最初の文字は大文字にする必要があることに注意してください。ここでは、新しいオブジェクトを作成し、コンストラクターのスコープを新しいオブジェクトに割り当て、コンストラクター内のメソッドを呼び出します。

上記のメソッドには何も問題がないように見えますが、2 つのインスタンスで呼び出されるコンストラクター内の SayWhat メソッドが同じ Function インスタンスではないことがわかります:

console.log(gf1.sayWhat == gf2.sayWhat); //false
ログイン後にコピー
同じメソッドを呼び出しても、異なるインスタンスを宣言するのはリソースの無駄です。コンストラクターの外側で、sayWhat 関数を最適化して宣言できます:

function Gf(name,bar){
  this.name = name;
  this.bar = bar;
  this.sayWhat = sayWhat
}
function sayWhat(){
  alert(this.name + "said:love you forever");
}
ログイン後にコピー
これにより、複数のインスタンスが同じメソッド インスタンスを複数回定義する問題は解決されますが、定義したsayWhat はグローバル スコープ メソッドですが、このメソッドを直接呼び出すことはできません。これは少し矛盾しています。特定のカプセル化プロパティを持つオブジェクトをよりエレガントに定義するにはどうすればよいでしょうか? JavaScript プロトタイプ オブジェクト パターンを見てみましょう。

プロトタイプオブジェクトパターン

プロトタイプ オブジェクトを理解する

関数を作成すると、その関数には、コンストラクターを通じて作成された関数のプロトタイプ オブジェクトを指すプロトタイプ属性が含まれます。平たく言えば、プロトタイプ オブジェクトは、他のオブジェクトに共有プロパティとメソッドを提供するメモリ内のオブジェクトです。

プロトタイプ モードでは、コンストラクターでインスタンス属性を定義する必要はなく、属性情報をプロトタイプ オブジェクトに直接割り当てることができます。

function Gf(){
  Gf.prototype.name = "vivian";
  Gf.prototype.bar = "c++";
  Gf.prototype.sayWhat = function(){
    alert(this.name + "said:love you forever");
  }
}
var gf1 = new Gf();
gf1.sayWhat();
var gf2 = new Gf();
ログイン後にコピー
コンストラクターとの違いは、ここでの新しいオブジェクトのプロパティとメソッドがすべてのインスタンスで共有できることです。つまり、gf1 と gf2 は同じプロパティとメソッドにアクセスします。プロトタイプ オブジェクトに割り当てる属性に加えて、いくつかの組み込み属性もあります。すべてのプロトタイプ オブジェクトには、プロトタイプ属性を含む関数へのポインターであるコンストラクター属性があります (さらに詳しく説明します)。この舌を巻くプロセスを写真でわかりやすく理解してみましょう:

すべてのオブジェクトにはプロトタイプ オブジェクト (プロトタイプ) があります。プロトタイプ オブジェクトには、プロトタイプ属性を含む関数を指すコンストラクター属性があります。Gf インスタンス gf1 と gf2 には両方とも、プロトタイプ オブジェクトを指す内部属性が含まれています (Firefox ブラウザーで表示)。はプライベート プロパティ プロトです)、オブジェクト内のプロパティにアクセスするときは、まずそのプロパティがインスタンス オブジェクトに存在するかどうかを尋ね、存在しない場合はプロトタイプ オブジェクトを探し続けます。

プロトタイプ オブジェクトを使用する
前の例では、プロトタイプ オブジェクトに属性を追加するときに、各オブジェクトに Gf.prototype を追加する必要があることがわかりました。上記のオブジェクト作成モードでは、リテラルを使用できることがわかりました。オブジェクトを作成します。ここで改善することもできます:

function Gf(){}
Gf.prototype = {
  name : "vivian",
  bar : "c++",
  sayWhat : function(){
    alert(this.name + "said:love you forever");
  }
} 
ログイン後にコピー
ここで特別な注意が必要な点が 1 つあります。関数が定義されるたびに、このオブジェクトも同時にプロトタイプ オブジェクトが作成されるため、コンストラクター属性はオブジェクト Gf を指さなくなりました。新しいコンストラクター属性を取得します。これは、基本的に元のプロトタイプ オブジェクトを上書きするために Gf.prototype を使用するため、コンストラクターは新しいオブジェクトのコンストラクター プロパティになり、Gf ではなく Object:

を指します。

var gf1 = new Gf();
console.log(gf1.constructor == Gf);//false
console.log(gf1.constructor == Object)//true
ログイン後にコピー

一般情况下,这个微妙的改变是不会对我们造成影响的,但如果你对constructor有特殊的需求,我们也可以显式的指定下Gf.prototype的constructor属性:

Gf.prototype = {
  constructor : Gf,
  name : "vivian",
  bar : "c++",
  sayWhat : function() {
    alert(this.name + "said:love you forever");
  }
}
var gf1 = new Gf();
console.log(gf1.constructor == Gf);//true
ログイン後にコピー

通过对原型对象模式的初步了解,我们发现所有的实例对象都共享相同的属性,这是原型模式的基本特点,但往往对于开发者来说这是把“双刃剑”,在实际开发中,我们希望的实例应该是具备自己的属性,这也是在实际开发中很少有人单独使用原型模式的主要原因。

构造函数和原型组合模式

在实际开发中,我们可以使用构造函数来定义对象的属性,使用原型来定义共享的属性和方法,这样我们就可以传递不同的参数来创建出不同的对象,同时又拥有了共享的方法和属性。

function Gf(name,bar){
  this.name = name;
  this.bar = bar;
}
Gf.prototype = {
  constructor : Gf,
  sayWhat : function() {
    alert(this.name + "said:love you forever");
  }
}
var gf1 = new Gf("vivian", "f");
var gf2 = new Gf("vivian1", "c");
ログイン後にコピー

在这个例子中,我们再构造函数中定义了对象各自的属性值,在原型对象中定义了constructor属性和sayWhat函数,这样gf1和gf2属性之间就不会产生影响了。这种模式也是实际开发中最常用的对象定义方式,包括很多js库(bootstrap等)默认的采用的模式。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート