ホームページ > 記事 > ウェブフロントエンド > JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析
JavaScriptにはクラスの概念がありませんが、ほとんどすべてがオブジェクトに基づいており、継承も実装できます。これがjsと他のOOP言語の最大の違いでもあります。 js について理解するのが難しいこと。以下、私の個人的な理解をお話しさせていただきます。
まず、オブジェクトの作成から始めましょう。一般に、次の方法があります:
1. オブジェクトインスタンスを作成し、それにプロパティとメソッドを追加します。
var person() = new Object(); person.name = 'mikej'; person.sayName = function(){ alert(this.name); }
2. 次のように書くこともできます:
var parson = { name : 'mikej', sayName : function(){ alert(this.name); } }
3. オブジェクトを作成するこれら 2 つの方法は非常に簡単ですが、同じモードを使用してオブジェクトを作成すると、大量の重複コードが生成されます。 。そこで、ファクトリー パターン:
function createPerson(name){ var p = new Object(); p.name=name; p.sayName = function(){ alert(this.name); }; return p; } var p1 = createPerson('mikej'); var p2 = createPerson('tom');
を使用すると、無制限のオブジェクトを作成できます。
4. Constructor と呼ばれる、ファクトリ パターンに似た別のメソッドがあります。 パターン:
function Person(name){ this.name=name this.sayName = function(){ alert(this.name); } this.say = function(){ alert('hi'); } } var p1 = new Person('mikej'); var p2 = new Person('tom');
ここで注意すべき点がいくつかあります: 作成されたオブジェクトは表示されず、ユーザーが使用する関数名は大文字の P (これは必須) の場合、p1 と p2 には person を指すコンストラクター属性があります。同時に、p1 と p2 は両方とも Object のインスタンスであると同時に、Person のインスタンスでもあります。
alert(p1.constructor == Person); //true alert(p1 instanceof Object); //true alert(p1 instanceof Person); //true
//5.11Update: PHP の観点からは、オブジェクトの作成プロセスをこのように考えるのは簡単でした。それから、new Person('mikej') を使用します。 code> はこのクラスをインスタンス化し、パラメータを渡します。しかし、実際にはそうではありません。作成プロセスは次のようになります。まず、空のオブジェクトを作成し、次に apply メソッドを使用します。つまり、最初のパラメーターは空のオブジェクトであり、2 番目のパラメーターはコンテキスト パラメーターです。 in Personal このオブジェクトは p1 を指します。 <code>new Person('mikej')
实例化了这个类,并且传入参数。但实际上并不是这样的,创建的流程应该是这样:首先,创建一个空对象,然后用apply方法,第一个参数是这个空对象,第二个参数是上下文的参数,这样Person中的this就会指向这个对象,也就是p1。
var p1 = new Person('mikej'); //上面代码就相当于 var p1 = {}; Person.apply(p1, ['mikej']);
构造函数模式看上去很好,但是它有一个弊端就是浪费内存,接上例
alert(p1.say == p2.say) //false
.为了避免这个缺陷,可是使用原型模式来创建对象,js中的每个对象都有一个JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析属性用来指向另外一个对象,这个对象的所有属性和方法都会被构造函数的实例继承,是共享的,这就意味着,我们可以把那些不变的属性和方法,定义到JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析对象上。
function Person(name){ this.name = name; } //Person的原型对象 Person.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析 = { say: function(){ alert('hi'); }, sayName: function(){ alert(this.name); } }; var p1 = new Person("mikej"); var p2 = new Person("tom"); p1.sayName(); p2.sayName(); //下面就可以看出方法实现了共享 alert(P1.say == P2.say) //true alert(P1.sayName == P2.sayName) //true
再来扩展一下上面的例子,使用原型来实现继承。
function Person(name){ this.name = name; } Person.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析 = { say: function(){ alert('hi'); }, sayName: function(){ alert(this.name); } }; function Programmer(){ this.say = function(){ alert('im Programmer, my name is ' + this.name); } } Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析 = new Person('mikej'); //手动修正构造函数 Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析.constructor = Programmer; var p1 = new Programmer(); console.dir(Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析.constructor);//Programmer console.dir(p1.constructor);//Programmer console.dir(p1);
Programmer的原型指向了Person的一个实例,那么所有的Programmer的实例都能继承Person和Person的原型了。
这里会有一个问题。
默认原型对象里有一个constructor属性,指向它的构造函数。而每一个实例也有一个constructor属性,会默认调用JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析对象的constructor属性。
假设没有Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析 = new Person('mikej');
Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析.constructor是指向Programmer的。p1的构造也指向Programmer
alert(Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析.constructor == Programmer) //true alert(p1.constructor == Programmer) //true
但有了这句Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析 = new Person('mikej');
Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析.constructor = Programmer;コンストラクター パターンは優れているように見えますが、メモリを浪費するという欠点があります。この問題を回避するには、オブジェクトを作成するためのプロトタイプ モード
。js 内の各オブジェクトには、別のオブジェクトを指すプロトタイプ属性があります。このオブジェクトのすべてのプロパティとメソッドが構築されます。インスタンスの継承関数は共有されます。これは、プロトタイプ オブジェクトで変更されていないプロパティとメソッドを定義できることを意味します。
console.dir(p1);
上記の例を拡張し、プロトタイプを使用して継承を実装してみましょう。
rrreeeProgrammer のプロトタイプが person のインスタンスを指すと、すべての Programmer インスタンスは person と person のプロトタイプを継承できます。
ここで質問があります。
デフォルトのプロトタイプオブジェクトには、そのコンストラクターを指すコンストラクター属性があります。各インスタンスにはコンストラクター属性もあり、デフォルトでプロトタイプ オブジェクトのコンストラクター属性を呼び出します。Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析 = new Person('mikej');
がないと仮定します。Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析.constructor は Programmer を指します。 p1 の構築も Programmer を指します🎜rrreee🎜 しかし、この文では Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析 = new Person('mikej');
となり、🎜🎜Programmer.JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析.constructor は Person 構築である Object を指します。 .JavaScript プロトタイプとプロトタイプ チェーンの詳細な分析 が指すオブジェクトの。 p1.constructor もオブジェクトを指します。ただし、p1 は明らかにコンストラクター Programmer によって生成され、継承の混乱を引き起こすため、コンストラクター (以下のコード) を手動で修正する必要があります。 🎜rrreee🎜それでは、プロトタイプ チェーンを見てみましょう: 🎜rrreee🎜このコードの結果は 🎜🎜🎜🎜🎜 p1 が Programmer のインスタンスであり、Programmer のプロトタイプが person であることがわかります。 Personal のプロトタイプは Object であり、インターネット上では JS のオブジェクトです。これがプロトタイプチェーンです。つまり、JavaScript の継承はプロトタイプチェーンに基づいて実装されます。 🎜🎜🎜以上がJavaScript プロトタイプとプロトタイプ チェーンの詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。