1. 程式人生 > 其它 >前端面試題21----js的繼承方法

前端面試題21----js的繼承方法

技術標籤:前端面試題javascriptes6

js繼承的幾種方法和es6繼承方法

繼承方法

原型鏈繼承

1.基本思想

利用原型鏈來實現繼承,超類的一個例項作為子類的原型

2、具體實現

function F() {}

    //原型屬性,原型方法:

    F.prototype.name="Lee";

    F.prototype.age=33;

    F.prototype.run=function(){

        return this.
name+" "+this.age+" running"; } var f = new F(); console.log(f.name); console.log(f.run);

3.優缺點

1)優點

  • 簡單明瞭,容易實現
  • 例項是子類的例項,實際上也是父類的一個例項
  • 父類新增原型方法/原型屬性,子類都能訪問到

2)缺點

  • 所有子類的例項的原型都共享同一個超類例項的屬性和方法
  • 無法實現多繼承
  • 在建立子類的例項時 不能向父類的建構函式傳遞引數

建構函式繼承

1。基本思想

通過使用call、apply方法可以在新建立的物件上執行建構函式,用父類的建構函式來增加子類的例項

2、具體實現

function F() {

        // 屬性

        this.name = name || 'dragon';

        // 例項方法

        this.sleep = function(){

            console.log(this.name + '正在睡覺!');

        }

    }

    function C(name){

        F.call(this);

        this.name = name || 'Tom';

    }

    var c=new C()

    console.
log(c.name); console.log(c.sleep());

3.優缺點

1)優點

  • 簡單明瞭,直接繼承超類建構函式的屬性和方法

2)缺點

  • 無法繼承原型鏈上的屬性和方法

例項繼承

1.基本思想

為父類例項新增新特性,作為子類例項返回

2.具體實現

function F() {

        // 屬性

        this.name = name || 'Animal';

        // 例項方法

        this.sleep = function(){

            console.log(this.name + '睡覺');

        }

    }

    function C(name){

        var instance = new F();

        instance.name = name || 'Tom';

        return instance;

    }

    var c = new C();

    console.log(c.name);

    console.log(c.sleep());

3.優缺點:
1)缺點:

  • 不限制呼叫方式,不管是new 子類()還是子類(),返回的物件具有相同的效果

2)缺點:

  • 例項是父類的例項,不是子類的例項
  • 不支援多繼承

組合繼承

1.基本思想

利用構造繼承和原型鏈組合

2.具體實現

function F() {

        // 屬性

        this.name = name || 'Animal';

        // 例項方法

        this.sleep = function(){

            console.log(this.name + '正在睡覺!');

        }

    }

    function C(name){

        F.call(this);//建構函式繼承

        this.name = name || 'Tom';

    }

    C.prototype = new F();//原型繼承

    var q=new C();

    console.log(q.name);

    console.log(q.sleep());

3.優缺點

1)優點

  • 解決了構造繼承和原型鏈繼承的兩個問題

2)缺點

  • 實際上子類上會擁有超類的兩份屬性,只是子類的屬性覆蓋了超類的屬性

原型式繼承

1.基本思想

採用原型式繼承並不需要定義一個類,傳入引數obj,生成一個繼承obj物件的物件

2、具體實現

var obj = {
       name: "qw",
        age: "12",
        ada:"asd"
    }

    function F(o) {

        function C() {}

        C.prototype = o;

        return new C();
    }
   var q= F(obj)

    console.log(q.name);

    console.log(q.age);

3.優缺點

1)優點:

  • 直接通過物件生成一個繼承該物件的物件

2)缺點:

  • 不是類式繼承,而是原型式基礎,缺少了類的概念

寄生式繼承(原型式+工廠模式 )

原型式+工廠模式
解決了組合繼承兩次呼叫建構函式的問題

1.基本思想

建立一個僅僅用於封裝繼承過程的函式,然後在內部以某種方式增強物件,最後返回物件

2、具體實現

//臨時中轉函式

    function obj(o) {

        function F() {}

        F.prototype = o;

        return new F();

    }

    //寄生函式

    function create(o){

        var q= obj(o);

        //可以對f進行擴充套件

        q.sleep = function(){

            return this.name+”睡覺”;

        }

        return q;

    }

    var box = {

        name: 'Lee',

        age: 100,

        family: ['Dad', 'Mom', 'Sister']

    };

    var box1 = create(box);

    alert(box1.name);

    alert(box1.run());

3.優缺點
1)優點:

  • 原型式繼承的一種拓展

2)缺點:

  • 依舊沒有類的概念
//臨時中轉函式

    function obj(o) {

        function F() {}

        F.prototype = o;

        return new F();

    }

    //寄生函式

    function create(box,desk){

        var q = obj(box.prototype);

        q.construtor=d;

        d.prototype=q;

    }

    function B(name,age){

        this.name=name;

        this.age=age;

    }

    B.prototype.run=function(){

        return this.name + " " + this.age +  " running..."

    }

    function D(name,age){

        Box.call(this,name,age);

    }

//通過寄生組合繼承來實現

create(B,D);//替代D.prototype=new B();
 
    var d= new D('Lee',100);

    alert(d.run());

3.優缺點

1)優點:

完美實現繼承,解決了組合式繼承帶兩份屬性的問題

2)缺點:

 過於繁瑣,故不如組合繼承

ES6的繼承

通過extends關鍵字

class father{

        constructor(name){

            this.name=name

            this.names=[1,2,3]

        }

        getname(){

            console.log(this.name);

        }

    }

    class child extends father{

        constructor(name){

            super(name);

        }

        sayHello(){

            console.log("sayHello");

        }

        static hh(){

            console.log("hh")

        }

    }

    var cc=new child("juanjuan");

    cc.sayHello();

    cc.getname();  //juanjuan

    child.hh();  //hh

    cc.names.push("wqwq");

    var c1=new child("sasasa");

    console.log(c1.names)  //[1,2,3]