zoukankan      html  css  js  c++  java
  • javascript继承方式详解

    继承方式主要有六种:

    1、原型链继承  存在对象共享的问题

    2、构造函数继承  借助call apply方法实现  :函数复用性问题 每次实例化,都重新执行了一次父类,父类中的方法重复定义  

    3、组合模式(原型链+构造函数)构造函数继承属性,原型链继承方法  :解决了对象共享,但是属性继承出现两次

    4、原型方式 使用一个空间空函数

    5、寄生方式  在原型方式上增加额外了方法

    6、寄生组合方式(解决了属性继承出现2次的问题)

    1、原型链方式

    子类在继承父类时,是将子类的prototype指向父类的一个实例对象。 在子类实例化时,所有子类的实例都会共享父类的那个实例上(假设叫p)的属性和方法,如果p上有引用型的属性,则子类的实例可以修改该引用型的属性,导致其他实例上的该属性也被修改。

    //原型链方式
    function A(){
        this.name = 'lc';
        this.stus = ['a','b','c'];
    }
    A.prototype.introduce = function (){
        alert(this.name);
    }
    
    function B(){}
    B.prototype = new A();
    
    var s1 = new B();
    var s2 = new B();
    console.log(s1.stus);  //['a','b','c']  
    s1.stus.push('d');     //改变s1上的属性,会影响s2上的该属性
    console.log(s2.stus);  // ['a','b','c','d']

    如果改成下面的,则不会影响。

    //原型链方式
    function A(){
        this.name = 'lc';
        this.stus = ['a','b','c'];
    }
    A.prototype.introduce = function (){
        alert(this.name);
    }
    
    function B(){}
    B.prototype = new A();
    
    var s1 = new B();
    var s2 = new B();
    
    s1.stus = ['d'];   //在s1上增加了属性,  就近原则,不在查找原型链上的同名属性
    console.log(s1.stus);  //['d']
    console.log(s2.stus);  // ['a','b','c']

    2、构造函数方式继承

      共用构造函数,方法都是在内部定义,复函复用性问题无从谈起。

    //构造函数方式继承
    function A(name){
        this.name = name;
        this.type = 'parent';
        this.introduce = function (){ alert(this.name);}
    }
    A.prototype.sayhi = function (){
        alert(this.type);
    }
    function B(name,age){
        A.call(this,name);  //使用call方法 实现继承 但是父类中的方法重复定义 无复用性
        this.age = age;
        this.introduce = function (){ alert(this.name+this.age);}
    }
    
    var b = new B('lc',25);
    b.introduce(); //lc25
    b.sayhi();  //parent

    3、混合方式 (原型方式+构造函数方式) 

    使用构造函数继承属性,原型链继承方法

    但是有一点不好的地方:  使用原型链继承时,实际上属性也继承了,重复了。 

    function A(name){
        this.name = name;
        this.type = 'parent';
    }
    A.prototype.sayhi = function (){
        alert(this.type);
    }
    function B(name,age){
        A.call(this,name);
        this.age = age;
        this.introduce = function (){ alert(this.name+this.age);}
    }
    B.prototype = new A();

    4、原型式继承

    使用了一个中间空函数,实现继承后,返回一个对象。

    function extend(parent){
        function F(){}
        F.prototype = parent;
        return new F();
    }

     5、寄生式继承  在原型式的基础上,再为对象添加属性 方法

    function extend(parent){
        function F(){}
        F.prototype = parent;
        return new F();
    }
    
    function createObj(p){  
        var clone = extend(p);
        clone.name = 'hello';    
        clone.say = function (){}
        return clone;
    }

    6、寄生组合式继承

    在继承方法的时候,不再实例化父类型的构造函数,而是使用inheritPrototype方法. 使用一个中间空函数,让这个空函数去继承父类原型,然后实例化这个空函数(继承了父类prototype中的所有方法)。将子类的原型指向这个实例化的空对象即可。

    避免了实例化父类的构造函数。

    /* 寄生组合式继承 */
    function inheritPrototype(subType, superType) {
      // var obj= extend(superType.prototype);
      function F(){}
      F.prototype = superType.prototype;
      var obj= new F();
    
      //obj.constructor = subType;
      subType.prototype = obj;    //不可将subType的prototype直接指向superType,否则的话,对子类prototype的修改会反应到父类上,  引用型变量
    subType.prototype.constructor = subType;
    }

    对象冒充: 使用构造函数的方式声明类,将一个类的方法指向另一个构造函数(因为构造函数本身就是一个方法函数),实现继承

    function A(){
        this.name = {name1:'hello'};
        this.say = function (){ console.log(this.name);}
    }
    function B(){
        this.method = A;
        this.method();
        delete this.method;
    }
     var bObj = new B();
  • 相关阅读:
    相关博客
    读写锁
    vccode配置c++ 编译环境
    windows下内存检测工具
    定时器堆的实现的方法
    关于tcp send的再次思考
    关于一个socket在阻塞模式下是否还可以使用的实验
    windows下对socket的send和recv的超时设置,并附一个简洁明了的socket简单demo
    对于vector中高效删除中间元素的技巧
    ubuntu下后台服务的管理
  • 原文地址:https://www.cnblogs.com/lydialee/p/4780400.html
Copyright © 2011-2022 走看看