欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript繼承學(xué)習(xí)筆記【新手必看】

 更新時間:2016年05月10日 16:26:38   投稿:jingxian  
下面小編就為大家?guī)硪黄狫avaScript繼承學(xué)習(xí)筆記。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考

JavaScript作為一個面向?qū)ο笳Z言(JS是基于對象的),可以實現(xiàn)繼承是必不可少的,但是由于本身并沒有類的概念,所以不會像真正的面向?qū)ο缶幊陶Z言通過類實現(xiàn)繼承,但可以通過其他方法實現(xiàn)繼承。實現(xiàn)繼承的方法很多,下面就只是其中的幾種。

一. 原型鏈繼承

function Person() {  //被繼承的函數(shù)叫做超類型(父類,基類)
      this.name='mumu';
      this.age='18';
    }
    
    Person.prototype.name='susu';//當(dāng)屬性名相同時需就近原則,先在實例里面查找,沒找到再到原型里找
       
    function Worker(){ //繼承的函數(shù)叫做子類型(子類,派生類)
      this.job='student';
    }

    Worker.prototype=new Person();//通過原型鏈繼承,超類型實例化后的對象實例,賦值給子類的原型屬性
    var p2=new Worker(); 

    console.log(p2.name);
    console.log(p2 instanceof Object);//ture 所有的構(gòu)造函數(shù)都繼承自O(shè)bject

以上實現(xiàn)繼承關(guān)鍵在于:Worker.prototype=new Person();  將Worker的原型成為Person的一個實例,通過原型鏈繼承。

注意:在使用原型鏈實現(xiàn)繼承時,不能使用對象字面量創(chuàng)建原型方法,因為這樣會中斷關(guān)系而重寫原型鏈。

原型鏈繼承問題:

1.出現(xiàn)引用共享問題,他們還是共用一個空間,子類會影響父類

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.在創(chuàng)建子類型的實例時,不能像超類型的構(gòu)造函數(shù)中傳遞參數(shù)。

那么如何解決原型鏈的兩個問題呢?那就繼續(xù)看下面的繼承方式吧~

二. 借用構(gòu)造函數(shù)繼承(也叫對象冒充,偽造對象或經(jīng)典繼承)

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','學(xué)生'); 
  p1.bodys.push('hand') ;
  var p2=new Worker();

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

簡單分析下以上使用借用構(gòu)造函數(shù)的原理:Person.call(this,name,age);這句代碼調(diào)用父級構(gòu)造函數(shù),繼承父級屬性,使用call方法調(diào)用Person構(gòu)造函數(shù)改變函數(shù)執(zhí)行時候的this,  這里的this-> new出來的一個Worker對象  構(gòu)造函數(shù)偽裝方法:把Worker傳給上面的Person。

當(dāng)引用類型放在構(gòu)造函數(shù)里面的時候就不會被共享,所以p2不受影響。

這里借用構(gòu)造函數(shù)繼承方式就解決了原型鏈不能傳遞參數(shù)以及引用類型共享的問題。

小知識:call()和apply()方法可以改變函數(shù)執(zhí)行的作用域, 簡言之就是改變函數(shù)中this指向的內(nèi)容。

call()和apply()都接受兩個參數(shù):第一個是在其中運行函數(shù)的作用域,另一個是傳遞的參數(shù)。

call和apply的區(qū)別就是參數(shù)的不同.
call中的參數(shù)必須是一個個枚舉出來的.
apply中的參數(shù)必須是數(shù)組或者是arguments對象

那么問題來了:為什么p1.showName()結(jié)果是錯誤的呢?----因為借用構(gòu)造函數(shù)繼承方式只能繼承構(gòu)造函數(shù)里的屬性和方法。這里也就發(fā)現(xiàn)了借用構(gòu)造函數(shù)的一個問題。

注意:由于把方法都放在構(gòu)造函數(shù)里,每次我們實例化就會分配內(nèi)存空間給它造成資源的浪費,所以一般我們都是把方法放在原型里,屬性放在構(gòu)造函數(shù)里。


借用構(gòu)造函數(shù)繼承問題:

因為借用構(gòu)造函數(shù)只能繼承構(gòu)造函數(shù)里的屬性和方法,在超類型的原型中定義的方法對子類而言是不可見的,所以就相當(dāng)于沒有了原型。結(jié)果所有的方法都只能在構(gòu)造函數(shù)里定義,因此就沒有函數(shù)復(fù)用了。

那么如何解決借用構(gòu)造函數(shù)所產(chǎn)生的問題呢?那就要看下面這種繼承方式了

三. 組合繼承(偽經(jīng)典繼承)

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);//借用構(gòu)造函數(shù)
    this.job=job;
  }
  
  Worker.prototype=new Person();//原型鏈繼承
  var p1=new Worker('mumu','18','學(xué)生'); 

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

組合繼承:將原型鏈與借用構(gòu)造函數(shù)結(jié)合。

思路:通過使用原型鏈實現(xiàn)原型上的屬性和方法繼承,借用構(gòu)造函數(shù)實現(xiàn)實例屬性的繼承

以上的例子Person.call(this,name,age);借用構(gòu)造函數(shù)繼承了屬性

Worker.prototype=new Person();原型鏈繼承了方法 , 避免了兩者的缺點,融合了它們的優(yōu)點,成為最常用的繼承模式。

組合繼承的問題:

調(diào)用兩次超類型構(gòu)造函數(shù),一次是在創(chuàng)建子類型原型時,另一次是在子類型的構(gòu)造函數(shù)內(nèi)部。

要解決這個問題就要用到寄生組合式繼承方式了。

四. 原型式繼承

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]}

簡單分析下:function object(proto)是一個臨時中轉(zhuǎn)函數(shù),里面的參數(shù)proto表示將要傳遞進入的一個對象,F(xiàn)()構(gòu)造函數(shù)是臨時新建的對象,用來存儲傳遞過來的對象,F(xiàn).prototype = proto;將對象實例賦值給F構(gòu)造函數(shù)的原型對象,最后返回傳遞過來的對象的對象實例。原型式繼承還是會共享引用類型的屬性。

五. 寄生式繼承

//臨時中轉(zhuǎn)函數(shù)  
function object(proto) {
    function F() {}
    F.prototype = proto;
    return new F();
  }

  //寄生函數(shù)
  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());寄生組合式繼承

六. 寄生組合式繼承

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

  //寄生函數(shù)
  function create(Person,Worker){
    var f=object(Person.prototype);//創(chuàng)建對象
    f.constructor=Worker;//調(diào)整原型構(gòu)造指針,增強對象
    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','學(xué)生');
p1.showName();

這種方法也是現(xiàn)在實現(xiàn)繼承方法中最完美的,也是最理想的。

以上這篇JavaScript繼承學(xué)習(xí)筆記【新手必看】就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論