码迷,mamicode.com
首页 > Web开发 > 详细

JS中的继承

时间:2019-07-04 14:37:55      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:接口继承   --   属性   typeof   转化   复用   spl   func   ceo   

js中只有 实现继承, 没有接口继承.
 
1.使用原型实现继承
 
  构造函数,对象实例 中都有指向 原型对象的指针
  但是构造函数实例和对象实例二者并没有直接联系(除了对象实例是用构造函数new出来这一点)
 
  试想,当类型A的原型对象 是其它类型(比如B类型)的 对象实例(b) 的时候
  那么A的prototype指向了b
      如果b本身的原型对象中的contructor指向了B,那么A继承自B
      如果b本身的原型对象是C类型的对象实例,那么A继承B,B继承C
      如果c本身的原型对象是 ...
      继续重复上面的步骤, 就形成了原型链
 
                                  TypeB                          TypeB.prototype
 
                     bridge(TypeA.prototype | instanceB)
  
  TypeA
 
  instanceA
 
 
  如上图:
    TypeA 以及 instanceA 都有指针指向 bridge(它既是TypeA的原型对象,又是TypeB的instance)
    既然 bridge是TypeB的对象实例,那么自然有指针指向TypeB的原型对象(TypeB.prototype)
    这时候instanceA 拥有了所有TypeB.prototype上的属性和方法.
    而 TypeB.prototype 上有constructor属性指向TypeB,instanceA也可以说是TypeB类型
 
  记住,无论原型链有多少环节,它总会有个末端,末端类型的原型对象 它是个Object类型的实例.
  所以会继承Object的所有属性和方法
 
确定原型与实例之间的关系
  使用instanceof操作符 或者 Xxxx.prototype.isPrototypeOf(instance) 函数.
  只要在这个instance的原型链上出现过的构造函数,它们就会返回true,表示是这个类型.
 
一定要先确定原型对象,然后再在原型上添加/覆盖 原型上的方法.
而且,添加或覆盖 属性/方法 的时候,不要使用字面量的形式.那会切断和父级的链接.
 
单独使用原型实现继承的缺点:
  ①.在创建对象的几种方式中,提到过原型模式.
    如果属性是引用类型的时候,会引发问题,所以这样的属性要放到构造函数中,而非原型对象上.
    但是,使用原型进行继承,会把别的类型的实例当做原型对象,
    那么别的实例中定义的属性,自然成为了本类型的原型属性,但这是个引用类型的属性,又回到了上面的问题
  ②.没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数. // todo 如何理解?
由于上述缺点,js中在实现继承的时候,不会单独的使用原型 来实现.
 
 
2.借用构造函数
  原理很简单,就是在子构造函数中,调用超类的构造函数.
 
  function Super(name){ this.name = name; }
  function Child(){
    Super.call(this,"my name"); // 继承Super
    this.age = 30 ; // 定义实例属性
  }
  console.log(new Child().name);//display ‘my name‘
 
  这个方式对比单独使用原型的好处是,可以向超类型传递参数.
  坏处是,构造函数模式的通病,定义的方法无法复用.而且超类型原型上的属性和方法,无法被继承.
  所以,开发中也不会单独使用这种模式来实现继承.
 
3.组合继承
  组合使用原型与借用构造函数来实现继承.
  原理很简单,超类实例属性用借用构造函数来继承;超类的原型属性和方法,用原型来继承.
  这种模式,是最经典的实现继承的方式.可以使用instanceof 以及 isPrototypeOf 来检查.
    
  function Super(name){
    this.name = name ;
  }
  Super.prototype.shareProp = "shareProp";
  Super.prototype.sayName = function(){
    console.log(this.name);
  }
 
  function Child(name ,age){
    Super.call(this,name);
    this.age = age ;
  }
  Child.prototype = new Super();
  Child.prototype.constructor = Child ;
  Child.prototype.sayAge = function(){
    console.log(this.age);
  };
 
  var c = new Child(); // 这时候实例c就拥有了 name,age,shareProp 属性,以及 sayName,sayAge 方法
 
  组合继承的缺点是
    会调用两次超类构造函数: new Super() 以及 Super.call(this,xxx);
    这算是个小缺点吧.
 
 
4. 原型式继承
  在已有对象实例的情况下,借助它创建新的对象实例,而不用自定义新的类型.
  function createObject(origin){
    function F(){}
    F.prototype = origin ;
    return new F();
  }
 
  var origin = {
    name:"origin",
    friends:["a","b","c"]
  };
  var one = createObject(origin);
  one.friends.push("d");
  var another = createObject(origin);
  another.friends.push("e");
 
  console.log(origin.friends); //display a ~ e
 
  以上的函数,在ES5中已经标准化了, 即
    Object.create(origin,opts);
      origin : 参考对象.(该对象会被浅复制,然后赋给新对象)
      opts : 是指描述 加入到新对象的附加属性/方法;
            格式和 defineProperties()中定义特性的格式一样{name:{value:"xx"},age :{ value : 20 }}
 
5. 寄生式继承
  在原型式继承上 进行了封装.
  不过耦合性太高,复用度不好.
  function CreateAdvObject(origin){
    //或者是 var clone = Object.create(origin); 只要可以生产对象就可以
    var clone = createObject(origin);
    clone.sayName = function(){}
    return clone;
  }
 
 
6. 寄生组合式继承
  为了解决 组合继承中 调用了两次超类构造函数的问题.就是为了更高效一些.
  被称为 最完美的继承方式
  思路就是:
    不必为了指定子类型的类型,而去调用构造函数,只需要一个超类原型对象的副本而已.
    那么,这个副本,就由寄生式继承来创建吧.
    换句话说,将调用超类的构造函数做子类原型 ,转化为copy超类原型给子类用
 
    function InheritPrototype(targetType , superType){
      targetType.prototype = Obeject.create(superType.prototype) ;
      targetType.prototype.constructor = superType ;
    }
 
    function Super(){}
    function Child(){
      Super.call(this, arguments);
    }
 
    // 代替了原来的 两段代码
    // Child.prototype = new Super(); Child.prototype.constructor = Super;
    InheritPrototype(Child,Super);
 
    Child.prototype.sayChild = function(){
      console.log("sayChild");
    }
 
 
 

JS中的继承

标签:接口继承   --   属性   typeof   转化   复用   spl   func   ceo   

原文地址:https://www.cnblogs.com/lmxxlm-123/p/11131892.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!