ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript オブジェクト指向 - プロトタイプの書き換え

JavaScript オブジェクト指向 - プロトタイプの書き換え

黄舟
黄舟オリジナル
2017-01-19 15:14:501661ブラウズ

前回の記事では、プロトタイプのメモリモデルを紹介し、4枚の写真を通してプロトタイプの各段階のステータスを分析しました。以下では、まず、一般的に使用されるプロトタイプおよびオブジェクトのプロパティ検出方法をいくつか紹介します。前回の記事の person クラスを例に挙げます。 person クラスを作成するコードは次のとおりです。

function Person(){};
 
Person.prototype.name = "Leon";
Person.prototype.age = 22;
Person.prototype.say = fucntion(){
  alert(this.name + "," + this.age);
}
 
var p1 = new Person();
var p2 = new Person();
p2.name = "Ada";
 
p1.say();
p2.say();

1. オブジェクトが特定の関数のプロトタイプであるかどうかを検出する

alert(Person.prototype.isPrototypeOf(p1));    //true

このメソッドは、プロトタイプであるかどうかを検出します。 p1のは人物です。

2. オブジェクトのコンストラクターを検出します

alert(p1.constructor == Person);    //true

3. 属性が独自の属性であるかどうかを検出します

alert(p1.hasOwnProperty("name"));   //false
alert(p2.hasOwnProperty("name"));   //true

オブジェクト p1 は独自の空間に name 属性を持たないため、false を返します。オブジェクト p2 は name 属性を再割り当てし、その空間に name 属性が存在するため、true を返します。

4. delete を使用して独自の空間内の属性を削除する

delete p2.name;
p2.say();
alert(p2.hasOwnProperty("name")); //false

上記のコードに示すように、delete を使用してオブジェクトの独自の空間内の属性を削除できます。

5. in 属性を使用して、オブジェクトがプロトタイプまたはそれ自体に特定の属性を含んでいるかどうかを検出します

alert("name" in p1); //在原型中有,所以为true
alert("name" in p2); //在自己的空间中有,所以为true

属性がプロトタイプまたは独自の空間で見つからない場合、結果は false になります。

6. プロトタイプに特定の属性が存在するかどうかを検出するカスタム メソッド

function hasPrototypeProperty(obj,prop){
  return(!obj.hasOwnProperty(prop) && (prop in obj));
}

上記のコードでは、プロトタイプに特定の属性が存在するかどうかを検出するメソッドをカスタマイズしました。このメソッドは次のように使用できます。

p1 オブジェクトの name 属性はプロトタイプに存在するため true を返しますが、p2 オブジェクトの name 属性は独自の空間にあるため false を返します。

プロトタイプを書き直す

前と同じようにコードを書くと、大量の person.prototype.xxx ステートメントが存在し、読みやすく理解するのは簡単ではありません。プロトタイプを Json に似た形式で書き換えることができます。 コードは次のとおりです。

alert(hasPrototypeProperty(p1,"name")); //true
alert(hasPrototypeProperty(p2,"name")); //false

上記のメソッドを使用してプロトタイプを書き換えた後、プロトタイプは書き換えられており、 person.prototype を通じて指定されていないため、このときのコンストラクターはその場合、それは人を指すのではなく、オブジェクトを指します。

//重写原型
Person.prototype = {
  name:"Leon",
  age:22,
  say:function(){
    alert(this.name+ "," + this.age);
  }
}
var p1 = new Person();
p1.say();

コンストラクターがプログラムにとって本当に重要な場合は、プロトタイプ ポインターを json で宣言できます。

alert(p1.constructor == Person); //false

プロトタイプの書き換えに関する問題

プロトタイプを書き直すと、次のような問題が発生する可能性があります。次に、まず問題を引き起こすプロトタイプの書き換えられたコードを見て、コードの各段階でメモリ モデルを分析してみましょう。コードは次のとおりです。

Person.prototype = {
  constructor:Person, //手动指定constructor
  name:"Leon",
  age:22,
  say:function(){
    alert(this.name+ "," + this.age);
  }
}

上記のコードでは、まず person クラスを作成しました。このとき、person プロトタイプのメモリ モデルは次のようになります。

JavaScript オブジェクト指向 - プロトタイプの書き換え

次に、p1 オブジェクトを作成しました。次に、 Person プロトタイプに、sayHi() メソッドを追加しました。このとき、Person プロトタイプのメモリモデルは以下のようになります。

// 创建Person类
function Person(){}
 
var p1 = new Person();
//在Person的原型上添加了sayHi()方法
Person.prototype.sayHi = function(){
  alert(this.name + "Hi!");
}
p1.sayHi();   //输出: undefined:hi!
 
// 对Person原型进行重写
Person.prototype = {
  constructor:Person, //手动指定constructor
  name:"Leon",
  age:22,
  say:function(){
    alert(this.name+ "," + this.age);
  }
}
 
var p2 = new Person();
p2.sayHi();
 
p2.say();//正确
p1.say();//报错

JavaScript オブジェクト指向 - プロトタイプの書き換え


この状態では p1 オブジェクト自身の空間には name 属性が存在しないので、現在のメモリモデルに注目してください。 Person プロトタイプなので、p1.sayHi() メソッドが実行されると、this.name 属性は未定義となり、最終的な出力結果は undefine:hi! になります。

次に、Person プロトタイプを書き直し、いくつかのプロパティとメソッドをプロトタイプに追加しました。

var p1 = new Person();
//在Person的原型上添加了sayHi()方法
Person.prototype.sayHi = function(){
  alert(this.name + "Hi!");
}
p1.sayHi();   //输出: undefined:hi!

このときのプロトタイプのメモリモデルは以下の通りです:

JavaScript オブジェクト指向 - プロトタイプの書き換え

プロトタイプが書き換えられた後、JavaScript は新しいプロトタイプのオブジェクトを指し、そのプロトタイプの _ を指します。最初に作成された p1 オブジェクト proto_ 属性は依然として前のプロトタイプ オブジェクトを指します。

この時点で、p1.sayHi() を実行すると、プログラムはエラーを報告しませんが、p1 オブジェクトとそれが指すプロトタイプに name 属性が存在しないため、実行結果はまだ未定義:hi! になります。 。

最後に、プロトタイプを書き換えた後、オブジェクト p2 を作成します。

// 对Person原型进行重写
Person.prototype = {
  constructor:Person //手动指定constructor
  name:"Leon",
  age:22,
  say:function(){
    alert(this.name+ "," + this.age);
  }
}
p1.sayHi();   //输出: undefined:hi!

この時のプロトタイプメモリモデルは以下の通りです。

JavaScript オブジェクト指向 - プロトタイプの書き換え

新しく作成されたp2オブジェクトの_proto_属性は、この時に書き換えられたプロトタイプオブジェクトを指します。この場合、p2 オブジェクトとそれが指すプロトタイプには SayHi() メソッドがないため、プログラムはエラーを報告します。

この時点で p1.say() メソッドが実行されると、p1 またはそれが指すプロトタイプには Say() メソッドが存在しないため、プログラムはエラーを報告します。

上記のプロトタイプ メモリ モデルの分析を通じて、プロトタイプの書き換え位置がオブジェクトのプロパティとメソッドに直接影響することがわかります。書き換え前に作成されたオブジェクトは、書き換え後に作成されたオブジェクトとは異なるプロパティとメソッドを持ちます。上記のメモリ モデル図を常に念頭に置いておかなければなりません。

上記は JavaScript オブジェクト指向プロトタイプの書き換えの内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。