Javascript の継承には、「オブジェクト偽装」と「プロトタイプ モード」の 2 つの形式があります。オブジェクトの偽装の本質は、この点を変更することであり、プロトタイプの継承とは、属性メソッドをコピーするという目的を達成するために、何らかの方法でプロトタイプを使用するか、プロトタイプをオーバーライドすることを指します。
このチュートリアルの動作環境: Windows7 システム、JavaScript バージョン 1.8.5、Dell G3 コンピューター。
Javascript 自体は Perl 言語の構文から発展したもので、本質的にはスクリプト言語であり、バージョンが更新されるにつれて、オブジェクト指向のシミュレーションが徐々に追加されます。
J のオブジェクト指向シミュレーションは、一般的には優れていると思います。なぜなら、どんな概念にも盲目的に従うことはできませんし、純粋に OOP のためだけに OOP を実行することもできないからです。オブジェクト指向の利点。これらの利点を得るために OOP に移行するのが最も賢明な選択であるため、Js はかなりうまくいっている。
Js の継承は多くの書籍で多くの種類と実装方法に注意深く分類されていますが、大きく分けてオブジェクト偽装とプロトタイプ方法の 2 種類があります。 これら 2 つの方法にはそれぞれ長所と短所があります。最初にそれらをここにリストし、次に最下位レベルとの違いを分析します:
(1) オブジェクトの偽装
function A(name){ this.name = name; this.sayHello = function(){alert(this.name+” say Hello!”);}; } function B(name,id){ this.temp = A; this.temp(name); //相当于new A(); delete this.temp; //防止在以后通过temp引用覆盖超类A的属性和方法 this.id = id; this.checkId = function(ID){alert(this.id==ID)}; }
オブジェクト B を構築するとき、temp を呼び出すことは、A のコンストラクターを開始することと同じです。ここでのコンテキスト内の this オブジェクトは B のインスタンスであることに注意してください。そのため、A コンストラクター スクリプトが実行されると、A のすべての変数とこのようにして、B が A の属性メソッドを継承するという目的は達成されます。
一時参照 temp を削除した後、B の A のクラス オブジェクト (インスタンス オブジェクトではないことに注意) への参照変更が維持されないようにするためです。temp を変更すると構造が直接変更されるためです。クラス A の (クラス A のオブジェクトではないことに注意してください) 多様性。
Js バージョンの更新の過程で、継承やより広範な目的を達成するためにこのコンテキストの切り替えをより便利に実行するために、call 関数と apply 関数が追加されたことがわかりました。それらの原則は同じですが、パラメーターのバージョンが異なるだけです (1 つは変数の任意のパラメーターで、もう 1 つはパラメーター セットとして配列で渡す必要があります)。ここでは、call を例として、call によって実装されるオブジェクト偽装の継承を説明します。
function Rect(width, height){ this.width = width; this.height = height; this.area = function(){return this.width*this.height;}; } function myRect(width, height, name){ Rect .call(this,width,height); this.name = name; this.show = function(){ alert(this.name+” with area:”+this.area()); } }
Call メソッドについての公式説明は、「オブジェクトのメソッドを呼び出して、現在のオブジェクトを別のオブジェクトに置き換える」です。
call (thisOb,arg1, arg2…)
これもオブジェクト偽装継承の一種です。実際、call メソッドが呼び出されたときに何が起こるかというと、コンテキスト環境変数 this が置き換えられます。myRect 関数本体では、this はインスタンスを指している必要があります。ただし、これをコンテキスト環境変数として使用して、Rect クラスのコンストラクターである Rect という名前のメソッドを呼び出します。
したがって、この時点で Rect を呼び出すと、これへの属性とメソッドの割り当ては、実際には myRect オブジェクトに対して実行されます。したがって、call と apply は継承のためだけの新しいメソッドではありませんが、継承をシミュレートするために使用できます。
これは、オブジェクトが継承されたふりをするものであり、この一連の代入プロセスを繰り返す限り、多重継承を実現できます。しかし、現状ではあまり大規模に利用されていません。
これには明らかなパフォーマンス上の欠陥があるため、これは OO の概念に関するものです。オブジェクトはメンバー メソッドのコレクションであると言います。オブジェクト インスタンスを構築するとき、これらのインスタンスには独自のメンバー変数だけが必要です。メンバー メソッドは、変数を操作する実行可能なテキスト領域です。この領域はインスタンスごとにコピーする必要はなく、すべてのインスタンスで共有できます。
ここで、オブジェクトを使用してシミュレートされたふりをする JS の継承に戻ります。このためにすべてのメンバー メソッドが作成されます。つまり、すべてのインスタンスはメンバー メソッドのコピー (メモリ リソースへの参照) を持ちます。極端な無駄遣い。
オブジェクトの偽装やプロトタイプ ドメインで変数やメソッドを継承できないなどの他の欠陥については言及する必要はありませんが、前述の致命的な欠陥で十分だと思います。ただし、特に親クラスのプロパティとメソッドがどのように継承されるかという原則を理解する必要があります。これは JS 継承を理解する上で非常に重要です。
[推奨学習: javascript 上級チュートリアル ]
(2) プロトタイプ メソッド
2 番目の継承メソッドはプロトタイプ メソッドです。いわゆるプロトタイプ メソッドの継承とは、属性メソッドのコピーの目的を達成するために、プロトタイプを使用するか、何らかの方法でプロトタイプをカバーすることを指します。実装にはさまざまな方法があり、フレームワークによって多少の違いはあるかもしれませんが、原理を理解すれば、理解できないことはありません。例 (特定の実装) を見てください:
function Person(){ this.name = “Mike”; this.sayGoodbye = function(){alert(“GoodBye!”);}; } Person.prototype.sayHello = function(){alert(”Hello!”);}; function Student(){} Student.prototype = new Person();
重要なのは、最後の文の Student プロトタイプ属性の値を、Person クラスによって構築されたオブジェクトに割り当てることです。ここでは、属性とメソッドがどのように割り当てられるかを説明します。親クラスのものがサブクラスにコピーされます。
Js オブジェクトがオブジェクトの属性を読み取るときは、常に最初に自身のドメインの属性リストをチェックします。存在する場合はそれを返します。それ以外の場合は、プロトタイプ ドメインを読み取ります。見つかった場合は、プロトタイプ ドメインを読み取ります。の場合、プロトタイプは他のものを指すことができるため、それを返します。オブジェクトなので、JS インタープリターは、プロトタイプ フィールドが指すオブジェクトのプロトタイプ フィールドを再帰的に検索し、プロトタイプ自体が見つかるまで停止します。今回は未定義になります。
这样看来,最后一句发生的效果就是将父类所有属性和方法连接到子类的prototype域上,这样子类就继承了父类所有的属性和方法,包括name、 sayGoodbye和sayHello。这里与其把最后一句看成一种赋值,不如理解成一种指向关系更好一点。
这种原型继承的缺陷也相当明显,就是继承时 父类的构造函数时不能带参数,因为对子类prototype域的修改是在声明子类对象之后才能进行,用子类构造函数的参数去初始化父类属性是无法实现的, 如下所示:
function Person(name){ this.name = name; } function Student(name,id){ this.id = id; } Student.prototype = new Person(this.name);
两种继承方式已经讲完了,如果我们理解了两种方式下子类如何把父类的属性和方法“抓取”下来,就可以自由组合各自的利弊,来实现真正合理的Js继承。下面是个人总结的一种综合方式:
function Person(name){ this.name = name; } Person.prototype.sayHello = function(){alert(this.name+“say Hello!”);}; function Student(name,id){ Person.call(this,name); this.id = id; } Student.prototype = new Person(); Student.prototype.show = function(){ alert(“Name is:”+ this.name+” and Id is:”+this.id);
总结就是利用对象冒充机制的call方法把父类的属性给抓取下来,而成员方法尽量写进被所有对象实例共享的prototype域中,以防止方法副本重复创 建。然后子类继承父类prototype域来抓取下来所有的方法。
如想彻底理清这些调用链的关系,推荐大家多关注Js中prototype的 constructor和对象的constructor属性,这里就不多说了。
更多编程相关知识,请访问:编程视频!!
以上がJavaScript 継承の 2 つの形式とは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。