//

作者:lofayo    发布于:

继承:就是让子对象获得父对象的属性和方法的一种方式。它的内容还是蛮复杂的,方式多样!

1、对象冒充实现的继承

           
理解:函数,既是方法,也是对象。一个函数(以方法身份)就可以作为另一个函数(以对象身份)的方法

function ClassA(sColor) {
    this.color = sColor;
    this.sayColor = function(){
        alert(this.color);
    }
}
// 构造函数中的 this 指向的是新创建的对象

function ClassB(sColor, sName) {
    this.newMethod = ClassA;    //ClassA中的this指向所属的对象
    this.newMethod(sColor);     //传入参数调用了
    delete this.newMethod;      //这个地方其实不太理解,既然delete,为啥还可以调用

    this.name = sName;
    this.sayName = function(){
        alert(this.name);
    }
}

var objA = new ClassA("red");
var objB = new ClassB("green", "luo");

objA.sayColor();        //"red"
objB.sayName();         //"green"

2、函数方法 call()和 apply() 实现的继承

           
理解:call()apply() 可以改变函数的作用对象,不同的对象可以调用同一函数

function ClassA(sColor) {
    this.color = sColor;
    this.sayColor = function(){
        alert(this.color);
    }
}
// 构造函数中的 this 指向的是新创建的对象

function ClassB(sColor, sName) {
    ClassA(this, sColor);   //this当前调用函数的对象,后面是参数

    this.name = sName;
    this.sayName = function(){
        alert(this.name);
    }
}

var objA = new ClassA("red");
var objB = new ClassB("green", "luo");

objA.sayColor();        //"red"
objB.sayName();         //"green"

3、原型链实现的继承

           
理解:原型链继承的本质就是,每个构造函数以及该构造函数生成的对象都有个prototype属性,都指向同一个原型对象。因此第二个函数的原型属性就可以用第一个函数的实例对象来充当,这样就构成了一层一层的继承关系。Class2.prototype = new Class1()

  • 原型属性等于不带参数的构造函数实例

      function SuperType(){
          this.superProperty = true;
      }
    
      SuperType.prototype.getSupProperty = function(){
          alert(this.superProperty);
      }
    
      function SubType(){
          this.subProperty = false;
      }
    
      SubType.prototype = new SuperType();    //子类原型等于父类实例
    
      SubType.prototyep.getSubProperty = function(){
          alert(this.subProperty);
      }
    

           
理解:子类原型对象等于构造函数的实例,这时候的构造函数没有传参数。如果要传参数,就会用到 curry化,但是就得将原型对象放在构造函数内部,这个是不允许的。

  • 对象冒充继承属性,原型继承方法

    function ClassA(sColor) {
      this.color = sColor;
    }
    
    ClassA.prototype.sayColor = function() {
      alert(this.color);
    }
    
    function ClassB(sColor, sName) {
    
      ClassA.call(this, sColor);
    
      this.name = sName;
    }
    
    ClassB.prototype = new ClassA();
    
    ClassB.prototype.sayName = function() {
      alert(this.name);
    }
    var objA = new ClassA("red");
    var objB = new ClassB("green", "luo");
    
    objA.sayColor(); //"red"
    objB.sayColor(); //"green"
    

4、原型链继承中构造函数带参数

在用原型链继承时,ClassB.prototype = new ClassA(),子类的原型对象上已经包含了父类构造函数里的自定义属性,因为没有传参数,所以这个值为空。但本质上,这个父类元素实例化赋给子类原型时,是可以带参数的,因此子类也就可以访问父类的这个属性,也可以理解为继承了这个属性(这是原型链的继承过程)。

  function ClassA(sColor) {
    this.color = sColor;
  }

  ClassA.prototype.sayColor = function() {
    alert(this.color);
  };

  function ClassB(sName) {
    this.name = sName;
  }

  // 将传入了参数的实例化对象赋给原型对象
  ClassB.prototype = new ClassA("green");

  var objA = new ClassA("red");
  var objB = new ClassB("luo");

  objA.sayColor(); //"red"
  alert(objB.name);     //"luo" 这个是本对象的,构造函数实例化时有的
  alert(objB.color);    //"green    这个是原型对象上有的,即带参数的实例化对象里的

        
这里面其实已经实现了“传参数的实例化对象赋给原型对象”,并且也继承了,到从代码的直观上来说,好像ClasB(sName)就一个name属性,其实它还有个color属性,只是放在了原型对象上,不够直观,容易误解。

==5、Obejct.setPrototypeOf(obj, newPrototype)实现的属性继承==

在第三中方案里,我们是通过“对象冒充”继承属性,“原型对象”继承方法。但终究感觉不太好,因为当ClassB.prototype = new ClassA()时,已经继承了属性,只是这个属性为空,并且还被“对象冒充”继承的属性给提前拦截了,覆盖了,访问不到这一层。

  function ClassB(sColor, sName) {
    this.name = sName;
      return (function(sColor) {
          ClassB.prototype = new ClassA(sColor);
      })();

      //按道理,这样应该也可行的
  Object.getPrototypeOf(this) = new ClassA(sColor);
  }

    var objB = new ClassB("green", "luo");
  alert(objB.color);    //undefined

        
我想实现的就是类似这种效果,但是都娶不到。

终于找到最优的解法了:

  ClassA.prototype.sayColor = function() {
    alert(this.color);
  };


function ClassB(sColor, sName) {
    this.name = sName;
      Object.setPrototypeOf(this, new ClassA(sColor));
  }

  ClassB.prototype.sayName = function() {
    alert(this.name);
  };

  var objA = new ClassA("red");
  var objB = new ClassB("green", "luo");

  objA.sayColor(); //"red"
  alert(objB.color);    //"green

Object.setPrototypeOf(this, new ClassA(sColor)); 完美的解决了原型链继承中,属性继承的方法,而不是“对象冒充”。只是这个方法的性能好像有点影响。

提个小问题:怎么感觉原型链上的这个this好像传的比较远???

现在才懂,但这毕竟是自己理解下亲自解决的方法。虽然说,这个方法肯定早已存在,它就在那个地方等着,只是你现在才发现而已。但是,一开始的全盘告诉你,你能接受得了吗?所以,一切都只能自己去发掘,既然它早已存在,对于你而言肯定是越早发现越好。

有一点,无论你发掘了什么东西,解决了什么问题,永远不要得意忘形,因为永远还有很多东西是你不知道的,你对于大千世界而言,永远都是渺小的。

吾生也有涯,而知也无涯,以有涯随无涯,殆矣。

而人生,就是这种学习探索的过程。

我才知道了,当你学习一样东西,如果你学到的真的就只是那一样东西,那最终你什么也没学到。你学到的是一些死货,没了多少的意义。你真正需要学习的是里面的设计思想,何为设计思想?就是里面设计的主线,也即机制,比如说:面向对象,你真的懂什么是面向对象么?所谓的面向对象就是一切皆对象,对象的身上附带着方法与属性,所有的使用也是基如此。为什么这样说呢?因为我花了很长时间都没有学懂的indexedDB原来也是奉行这一套,在此基础上执行原型链的那一套继承方式。

format_list_numbered

(无)

  1. 1. 1、对象冒充实现的继承
  2. 2. 2、函数方法 call()和 apply() 实现的继承
  3. 3. 3、原型链实现的继承
  4. 4. 4、原型链继承中构造函数带参数
  5. 5. ==5、Obejct.setPrototypeOf(obj, newPrototype)实现的属性继承==
vertical_align_top

Copyright © 2017 每天寻求一点变化

Powered by Hexo & Theme - Vateral