zoukankan      html  css  js  c++  java
  • JS继承方法

    1、原型链:

    每个构造函数都有一个原型对象,且有一个指针指向该原型对象(prototype),原型对象都包含一个指向构造函数的指针(constructor),而实例都包含一个指向原型对象的内部指针(proto)。若实例的原型是另一个构造函数的实例,该实例的原型有一个指向另一个原型的指针,层层递进,构成原型链。

    原型上的属性和方法为所有实例所共有,当访问一个实例属性时,首先会在实例中搜索该属性,如果没有找到该属性,则会继续搜索该实例的原型,沿着原型链网上搜索,到原型链末端或找到为止。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 子类
    function Sub(){
      this.property = 'Sub Property'
    }
    Sub.prototype = new Super()
    // 注意这里new Super()生成的超类对象并没有constructor属性,故需添加上
    Sub.prototype.constructor = Sub
    ```缺点:
     
    1.  包含引用类型的原型属性会被所有实例共享,一个实例对引用类型属性进行修改,就是直接修改原型上的该属性;
    2.  在创建子类型的实例时,没有办法给超类型的构造函数传递参数。
     
    注意:原型上的引用值属性和方法使用时均为指针,但构造函数中的不同,不同实例中的同名属性和方法也不相同!!!

    2、借用构造函数:

    1
    2
    3
    4
    5
    在子类型构造函数中,使用call或apply方法在将来新建的对象上执行父类构造函数
    function Sub(){
    Super.call(this,'参数')//将Super的属性和方法都复制了一遍
     this.property = 'Sub Property'
    }
    1. 实例并不是父类的实例,只是子类的实例
    2. 只能继承父类的属性和方法,不能继承父类原型上的属性/方法
    3. 无法实现函数复用(父类上的方法也都复制到最后的实例中,方法不能复用),每个子类都有父类属性和方法的副本,影响性能

    3、组合继承:

    使用原型链来实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承
    1
    2
    3
    4
    5
    6
    function Sub(){
     Super.call(this)              //第二次调用Super() Super中的属性和方法复制进来 this.property = 'Sub Property'
     }
     Sub.prototype = new Super()//第一次调用Super() Super.prototype上的方法则可以共享
     // 注意这里new Super()生成的超类对象并没有constructor属性,故需添加上
     Sub.prototype.constructor = Sub
    无论什么情况都会调用两次超类型构造函数,
    第一次是将子类的原型指向父类的实例,这样可以共享父类的原型上的属性和方法,但父类中的属性和方法会写入到子类的原型上;
    第二次是将父类中的属性和方法复制到子类构造函数中,会覆盖子类原型上的同名属性

    4、原型式继承:

    1
    2
    3
    4
    5
    function objectCreate(obj){
     function F(){}
     F.prototype = obj
     return new F()
     }
    但是新对象原型的那个对象(obj)中,引用类型的属性始终都会共享相应的值

    5、寄生式继承:

    创建一个仅仅用于封装继承过程的函数,然后在内部以某种方式增强对象,最后返回对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function objectCreate(obj){
     function F(){}
     F.prototype = obj
     return new F()
     }
     function createSubObj(superInstance){
     var clone = objectCreate(superInstance)//任何能够返回新对象的函数都适用
     clone.property = 'Sub Property'
     return clone
     }
    组合继承的问题是:会调用两次构造函数,(一次生成实例并作为子类的原型,一次是当做普通函数)导致父类中的属性会有两组:一组在子类的原型上;一组在实例上。
    解决这个问题的方法--------寄生组合式继承

    6、寄生组合式继承:

    结合寄生式继承和组合式继承,完美实现不带两份超类属性的继承方式。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function inheritPrototype(Super,Sub){
     var superProtoClone = Object.create(Super.prototype)
     superProtoClone.constructor = Sub
     Sub.prototype = Super
     }
     function Sub(){
     Super.call()
     Sub.property = 'Sub Property'
     }
     inheritPrototype(Super,Sub)

    7、ES6 extends继承

    类的实质是基于原型的和基于构造函数的语法糖

    类声明:class 类名 {类体} ;//类声明不会提升

    类表达式:let 类名 = class 类名 {类体}

    extends 来创建子类,并继承父类 : class 子类名 extends 父类名 {类体}

    1
    class Point{ ....   } typeof Point // "function" Point === Point.prototype.constructor // true

    类的数据类型就是函数,类本身就指向构造函数。

    使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。

    1
    2
    3
    4
    class Bar{
        doStuff(){console.log('stuff');}
    } var b = new Bar();
    b.doStuff();// "stuff"

    构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。

    1
    2
    3
    4
    5
    6
    //定义类 class Point{
     constructor((x, y){  this.x = x; this.y = y;
    }
    toString(){ return  '('  +  this.x +  ', '  +  this.y +  ')';
    }
    }
    constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。constructor方法默认返回实例对象(即this)
    类必须使用new调用,否则会报错。实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)
    Class 可以通过extends关键字实现继承:在子类的构造函数中,只有调用super之后,才可以使用this关键字,super代表父类的构造函数,子类的构造函数必须执行一次super函数。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class ColorPoint extends Point {
     consturctor(x,y,color){
     super(x,y); // 调用父类的constructor(x, y)
     this.color = color;
    }
     toString(){
     return this.color + " " super.toString();//调用父类的toString()方法
     }
    }

     

  • 相关阅读:
    自适应网页设计?
    布局设置加版心?
    bootstrap框架使用?
    Electron框架下,如何使用jquery?
    轮播插件swiper.js?
    表格出现滚动条设置?
    overflow问题--滚动设置?
    移动端页面适配ipad?
    移动端页面构建需注意?
    复杂的Sql分组
  • 原文地址:https://www.cnblogs.com/lihuijuan/p/9623377.html
Copyright © 2011-2022 走看看