ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript継承学習メモ【初心者必読】_JavaScriptスキル

JavaScript継承学習メモ【初心者必読】_JavaScriptスキル

WBOY
WBOYオリジナル
2016-05-16 08:59:482388ブラウズ

javascript はオブジェクト指向言語 (js はオブジェクトに基づいている) であるため、継承を実現するためには必須ですが、クラスの概念がないため、実際のオブジェクト指向プログラミングのようにクラスによる継承を実現することはできません。ただし、継承は他の方法でも実現できます。継承を実装するにはさまざまな方法がありますが、ここではそのうちのいくつかを紹介します。

1. プロトタイプ チェーンの継承

function person() {  //被继承的函数叫做超类型(父类,基类)
      this.name='mumu';
      this.age='18';
    }
    
    person.prototype.name='susu';//当属性名相同时需就近原则,先在实例里面查找,没找到再到原型里找
       
    function worker(){ //继承的函数叫做子类型(子类,派生类)
      this.job='student';
    }

    worker.prototype=new person();//通过原型链继承,超类型实例化后的对象实例,赋值给子类的原型属性
    var p2=new worker(); 

    console.log(p2.name);
    console.log(p2 instanceof object);//ture 所有的构造函数都继承自object

上記の継承を実装するための鍵は次のとおりです: worker.prototype=new person(); worker のプロトタイプを person のインスタンスに変換し、プロトタイプ チェーンを通じて継承します。

注: プロトタイプ チェーンを使用して継承を実装する場合、オブジェクト リテラルを使用してプロトタイプ メソッドを作成することはできません。これは、関係が壊れてプロトタイプ チェーンが書き換えられるためです。

プロトタイプ チェーンの継承の問題:

1. 参照共有の問題があります。これらは依然として同じ空間を共有しており、サブクラスは親クラスに影響を与えます。

function person() {  
      this.bodys=['eye','foot'];
    }
    
    function worker(){ 
    }

    worker.prototype=new person();
    var p1=new worker();
    p1.bodys.push('hand');
    var p2=new worker(); 
    console.log(p1.bodys);
    console.log(p2.bodys);

2. サブタイプのインスタンスを作成する場合、スーパータイプのコンストラクターにパラメーターを渡すことはできません。

では、プロトタイプチェーンの 2 つの問題を解決するにはどうすればよいでしょうか?次に、次の継承メソッドを見ていきます~

2. コンストラクター継承の借用 (オブジェクト偽装、偽オブジェクト、またはクラシック継承とも呼ばれます)

function person(name,age){
    this.name=name;
    this.age=age;
    this.bodys=['eye','foot'];
  }

  person.prototype.showname=function(){
    console.log(this.name);
  }

  function worker(name,age,job){
    person.call(this,name,age);
    this.job=job;//子类添加属性
  }

  var p1=new worker('mumu','18','学生'); 
  p1.bodys.push('hand') ;
  var p2=new worker();

  console.log(p1.name);
  console.log(p2.bodys);
  console.log(p1.showname());

借用したコンストラクターを使用する上記の原則の簡単な分析: person.call(this, name, age); このコードは、親コンストラクターを呼び出し、親プロパティを継承し、call メソッドを使用して person コンストラクターを呼び出して変更します。関数の実行時間 これは、this-> の新しい constructor 偽装メソッドからの worker オブジェクトです: worker を上の person に渡します。

参照型がコンストラクターに配置される場合、参照型は共有されないため、p2 は影響を受けません。

ここでは、プロトタイプ チェーンがパラメーターを渡すことができず、参照型が共有されるという問題を解決するために、コンストラクター継承メソッドが使用されています。

ヒント: call() メソッドと apply() メソッドは、関数の実行範囲を変更できます。つまり、関数内で this が指す内容を変更します。

call() と apply() はどちらも 2 つの引数を受け入れます。1 つ目は関数が実行されるスコープで、もう 1 つは渡された引数です。

呼び出しと適用の違いはパラメータの違いです。
呼び出し内のパラメータは 1 つずつ列挙する必要があります。
apply のパラメータは配列または引数オブジェクトである必要があります

次に、p1.showname() の結果がなぜ間違っているのかという疑問が生じます。 ----借用したコンストラクター継承メソッドは、コンストラクター内のプロパティとメソッドしか継承できないためです。コンストラクターの借用に関する問題もここで発見されます。

注: すべてのメソッドはコンストラクターに配置されるため、インスタンス化するたびにメモリ領域が割り当てられ、リソースの無駄が発生します。そのため、通常はメソッドをプロトタイプに配置し、属性をコンストラクターに配置します。 . .


借用コンストラクターの継承の問題:

借用したコンストラクターはコンストラクター内のプロパティとメソッドのみを継承できるため、スーパー型のプロトタイプで定義されたメソッドはサブクラスからは見えず、プロトタイプがないのと同じになります。その結果、すべてのメソッドはコンストラクター内でのみ定義できるため、関数の再利用はありません。

では、コンストラクターを借用することによって引き起こされる問題をどのように解決するのでしょうか?次に、次の継承メソッドを確認する必要があります。

3. 組み合わせ継承 (擬似古典継承)

function person(name,age){
    this.name=name;
    this.age=age;
  }

  person.prototype.showname=function(){
    console.log(this.name);
  }

  function worker(name,age,job){
    person.call(this,name,age);//借用构造函数
    this.job=job;
  }
  
  worker.prototype=new person();//原型链继承
  var p1=new worker('mumu','18','学生'); 

  console.log(p1.age);
  p1.showname();

結合継承: プロトタイプ チェーンを借用したコンストラクターと結合します。

アイデア: プロトタイプ チェーンを使用してプロトタイプ上の属性とメソッドの継承を実現し、コンストラクターを借用してインスタンス属性の継承を実現します。

上記の例 person.call(this,name,age); は、コンストラクターを借用してプロパティを継承します

worker.prototype=new person(); プロトタイプ チェーンはメソッドを継承し、両方の欠点を回避し、利点を統合して、最も一般的に使用される継承パターンになります。

結合継承の問題:

スーパータイプ コンストラクターは 2 回呼び出されます。1 回はサブタイプ プロトタイプの作成時、もう 1 回はサブタイプのコンストラクター内で呼び出されます。

この問題を解決するには、寄生結合継承を使用する必要があります。

4. プロトタイプの継承

function object(proto) {
    function f() {}
    f.prototype = proto;
    return new f();
  }

  var person = {
    name: 'mumu',
    friends: ['xiaxia', 'susu']
  };

  var anotherperson = object(person);
  anotherperson.friends.push('wen');
  var yetanotherperson = object(person);
  anotherperson.friends.push('tian');
  console.log(person.friends);//["xiaxia", "susu", "wen", "tian"]
console.log(anotherperson.__proto__)//object {name: "mumu", friends: array[4]}

簡単な分析: 関数オブジェクト (proto) は、一時的な通過関数です。内部のパラメーター proto は、渡されるオブジェクトを表します。 f () コンストラクターは、渡されたオブジェクトを格納するために使用される、一時的に新しく作成されるオブジェクトです。 prototype = proto; は、オブジェクト インスタンスを f コンストラクターのプロトタイプ オブジェクトに代入し、最後に渡されたオブジェクトのオブジェクト インスタンスを返します。プロトタイプの継承は引き続き参照型のプロパティを共有します。

5. 寄生継承

//临时中转函数  
function object(proto) {
    function f() {}
    f.prototype = proto;
    return new f();
  }

  //寄生函数
  function create(proto){
    var f=object(proto);
    f.love=function(){
      return this.name;
    }
    return f;
  }

  var person = {
    name: 'mumu',
    friends: ['xiaxia', 'susu']
  };

  var anotherperson = create(person);
  console.log(anotherperson.love());寄生组合式继承

6. 寄生結合継承

function object(proto) {
    function F() {}
    F.prototype = proto;
    return new F();
  }

  //寄生函数
  function create(Person,Worker){
    var f=object(Person.prototype);//创建对象
    f.constructor=Worker;//调整原型构造指针,增强对象
    Worker.prototype=f;//指定对象
  }
  
  function Person(name,age){
    this.name=name;
    this.age=age;
  }
  Person.prototype.showName=function(){
    console.log(this.name);
  }
  function Worker(name,age,job){
    Person.call(this,name,age);
    this.job=job;
  }
  
  create(Person,Worker);//寄生组合式继承
  var p1=new Person('mumu','18','学生');
p1.showName();

この方法は、現在の継承方法の中で最も完璧で理想的な方法でもあります。

上記の javascript 継承学習ノート【初心者必読】はすべて編集者が共有した内容ですので、ご参考になれば幸いです、script home を応援していただければ幸いです。

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