欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前端面试题21----js的继承方法

程序员文章站 2022-06-09 21:39:21
...

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]