この記事の内容は、JavaScript でのプロトタイプチェーンによる継承の分析に関するものです (コード付き)。必要な方は参考にしていただければ幸いです。
プロトタイプは、新しい関数を作成するときに自動的に生成され、プロトタイプには、プロトタイプを作成した関数オブジェクトを参照するコンストラクターも存在します。
__proto__ は、オブジェクトまたはインスタンスに組み込まれた [[prototype]] であり、オブジェクトを生成したオブジェクトのプロトタイプを指します。__proto__ は、アクセスできるようにブラウザーで提供されます。これは、 のポインティングによって形成されます。 __proto__ のチェーンはプロトタイプ チェーンと呼ばれます。プロトタイプ チェーンのリンク全体は次のとおりです: インスタンス オブジェクト- ->コンストラクターのプロトタイプ- ->オブジェクトのプロトタイプ- ->null。
オブジェクトのプロパティまたはメソッドにアクセスするとき、最初にこのオブジェクトから検索します。プロパティまたはメソッドがこのオブジェクトに存在しない場合は、プロパティまたはメソッドが見つかるまでプロトタイプ チェーンに沿って上方向に検索します。ヌルストップに達します。
これは、配列オブジェクトにプッシュ、ポップ、シフト、アンシフトなどのメソッドがない理由も説明していますが、
コンストラクター属性は、関数 (オブジェクト) を生成した関数 (オブジェクト) を指します)、
var a = function(){}; var b = new a(); var c = {}; var d = []; //以下皆为true console.log(b.constructor === a) //因为实例b是由构造函数产生的 console.log(a.constructor === Function)//函数a实际是Function的实例,同理 console.log(c.constructor === Object)//空对象c是Object的实例 console.log(d.constructor === Array)//空对象c是Object的实例 console.log(Object.constructor === Function)//Object自身就是一个构造函数,同理 console.log(Array.constructor === Function)//Array自身也是一个构造函数 //--------------------------------------------------------------- //首先__proto__指向的是产生该对象的对象的prototype, //也即a.prototype,prototype中也的constructor,回指创建该prototype的函数对象,也即函数a console.log(b.__proto__.constructor === a)
など ちなみに、instanceof、AinstanceofBは、Aのプロトタイプチェーンの中でBのプロトタイプを見つけることです。 見つかった場合はtrueを返し、見つからない場合はfalseを返します
//有个奇怪的现象,下面都返回true,这是为什么呢? //因为JS中一切都继承自Object,除了最顶层的null, //所以在Function的原型链中能找到Object.prototype console.log(Function instanceof Object) //而Object自身就是一个构造函数,因此在Object的原型链中也能找到Function.prototype console.log(Object instanceof Function)
上記の分析から、プロトタイプチェーンは継承のロジックを実装することができます。継承はオブジェクト指向において非常に重要な概念です
function Dog(name){ this.name = name; this.say1 = function(){ console.log(this.name) } } Dog.prototype.say2 = function(){ console.log(this.name) } Dog.prototype.test = 1 //say本来应该是所有Dog实例的共有方法, //如果放在构造函数中,那么就会导致没办法数据共享,每一个实例都有自己的属性和方法的副本,这是对资源的极大浪费 //如果放在Dog.prototype中,那么利用原型链的特性,就可以让所有实例共用一个方法, //需要注意的是,由于共用了一个方法,对属性的更改是对所有实例透明的 var dog1 = new Dog('lalala'); let dog2 = new Dog('wahaha'); dog1.test++;//2 dog2.test++;//3 console.log(dog1.say1 === dog2.say1)// false console.log(dog1.say2 === dog2.say2)// true //现在,我们可以尝试着去实现继承了 //我们是通过原型链去实现继承的, //之前的原型链是:Dog实例 --> Dog函数 --> Object --> null //那么现在的原型链需要改成 Dog实例 --> Dog函数 --> Dog父类(Animal函数) --> Object --> null //第一种方案,改变Dog函数的prototype,让他指向Animal的实例 function Animal(){ this.species = 'unknown'; } Dog.prototype = new Animal(); //这里改变后会导致prototype中的constructor改变 Dog.prototype.constructor = Dog; //第二钟方案,改变Dog函数的prototype,让他指向Animal的prototype function Animal(){} Animal.prototype.species = 'unknown'; Dog.prototype = Animal.prototype; //这里改变后会导致prototype中的constructor改变 Dog.prototype.constructor = Dog; //第三种方案,调用apply或call,将Animal的this绑定到Dog中 function Animal(){ this.species = 'unknown'; } function Dog(name){ Animal.apply(this, arguments); this.name = name; } //第四种方法,通过Object.create()方法实现继承,过滤掉了父类实例属性,Dog.prototype中就没有了Animal的实例化数据了 //这种方法也是ES6中Class被babel编译成ES5所用的方法 function Animal(){ this.species = 'unknown'; } function Dog(name){ Animal.apply(this, arguments); this.name = name; } //这里模拟了 Dog.prototype = Object.create(Animal.prototype) var f = function(){}; f.prototype = Animal.pototype; Dog.prototype = new f(); Dog.__proto__ = Animal; //这里改变后会导致prototype中的constructor改变 Dog.prototype.constructor = Dog; //现在就能访问到Animal中的species属性了 var dog = new Dog('lalala'); dog.species;//unknown
これらはプロトタイプを使用するいくつかの方法です。継承を実装するチェーン
上記の知識を使って、ES6 クラスを見てみましょう。この構文シュガーを使用すると、extends、static などのキーワードが提供されます。 、そして超、より深く明確な理解が得られ、コンストラクターとinstanceofの使い方に慣れ、プロトタイプチェーンに基づく継承方法についての理解が深まり、この知識が明確になりました。
以上がJavaScriptのプロトタイプチェーンによる継承分析(コード添付)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。