美文网首页我爱编程
js继承与实例化(个人整理)

js继承与实例化(个人整理)

作者: 博客专用马甲 | 来源:发表于2015-08-07 01:26 被阅读2310次

    对于js继承一直都是半懂半不懂的状态,感觉需要整理一下:

    参考自:
    JavaScript原型继承工作原理
    JavaScript实现继承的几种方式
    JavaScript继承方式详解

    1. 区分类继承和实例化的差别

    非常常用的类继承是这个样子的:
    B.prototype = new A()
    这时候特别容易和实例化给混淆了(反正我混了):
    b = new A()

    感觉不好玩了对不对,这个时候开始好奇new到底干了什么事情(理解原理非常重要的撒):

    创建类的示例 初始化 返回实例

    用代码表示如下:

    function New (f) { 
        var n = { '__proto__': f.prototype }; /*第一步*/ 
        return function () { 
            f.apply(n, arguments); /*第二步*/ 
            return n; /*第三步*/
         };
    }
    

    还是有点云里雾里,怎么区分什么时候是类继承,什么时候是实例化呢?
    呐,首先我先想到一切皆为函数,所以无论是实例化还是继承,本质上都是拥有A的属性(函数或者值)嘛,所以必须要想清楚js是怎么查找一个东西的属性的哇:

    当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止。

    用代码表示如下:

    function getProperty(obj, prop) {
        if (obj.hasOwnProperty(prop)){
            return obj[prop]
        }else if (obj.__proto__ !== null){
            return getProperty(obj.__proto__, prop)
        }else{
            return undefined
        }
    }
    

    恩,这下子可以解释两者区别了:
    B.prototype = new A() : B.prototype要找自己属性的时候:先看看自己有没有 --> 看看自己的proto(也就是A.prototype)有没有 --> 一路往上
    b = new A(): b找自己属性的时候:先看看自己有没有 --> 看看自己的proto(也就是A.prototype)有没有 --> 一路往上

    n年前收集了一张图,仔细看,就是我前面整理的内容了(不要晕,仔细看,此图博大精深):

    原型链解释.jpg

    对于原型链不理解的其实可以去看Typescript,对比Typescript和它生成出来的js代码,就容易理解了。

    2. js继承方式

    理解第一节以后,js继承方式什么的,so easy啦~

    心中只要记住,作为子类的我,只要能够拥有父类prototype里的属性,就可以算作继承了(个人理解,觉不对可举正)

    感觉可以用生孩子的例子贯穿这一节嘛~

    • 原型链继承(其实就是最开始1的那种继承)

      //父类
      var Animal = function(){
        //可以在构造函数里面直接设置属性~
        this.name = 'animal';
      }
      //也可以通过prototype
      Animal.prototype.say = function(){
        console.log('Animal here');
      }
      
      //子类
      var Dog = function(){
      
      }
      Dog.prototype = new Animal();
      //改写父类prototype
      Dog.prototype.name = 'dog';
      
      //创建实例
      var doge = new Dog();
      console.log(doge.name)  //'dog';
      doge.say()  //'Animal here';
      

      最传统的办法了,自己生

    • 构造继承(借用方法)

      //父类还是一样样的
      var Dog = function(){
          Animal.call(this);
          this.name = 'dog';
      }
      
      //创建实例
      var doge = new Dog();
      console.log(doge.name) //'dog';
      doge.say() //error;
      

    咦,哪里不对,怎么会error说没有这个方法?!!
    仔细看代码,要理解,Dog只是借用了Animal的构造方法,Animal的say方法是在prototype上的,当然找不到了,所以这种方法的问题就很明显啦,就是并没有依靠原型链关系,就像试管婴儿嘛,我只是借个肚子生小孩而已,基因还是我的(哈哈哈) 也就是说如果通过instanceof检查doge和Animal的关系,会发现返回没有关系的呦。

    • 实例继承
      var Dog = function(){
      var dog = new Animal();
      dog.name = 'dog';
      return dog;
      }

      //创建实例
      var doge = new Dog();
      console.log(doge.name)  //'dog';
      doge.say()  //'Animal here';
      console.log(doge instanceof Animal)  // true
      console.log(doge instanceof Dog)  // false
      

    额,就好象小明爸爸借隔壁老王过来生小明~~ 实例是父类的实例,而不是子类的实例。

    • 拷贝继承(暴力继承)
      var Dog = function(){
      var animal = new Animal();
      for(var attr in animal){
      this[attr] = animal[attr];
      }
      this.name = 'dog';
      }

      //创建实例
      var doge = new Dog();
      console.log(doge.name) //'dog';
      doge.say() //'Animal here';
      console.log(doge instanceof Animal) // false
      console.log(doge instanceof Dog) // true
      

    最野蛮的办法:把老王家的儿子抓过来,照着他的样子自己生一个

    • 组合继承
      var Dog = function(){
      Animal.call(this, arguments);
      this.name = 'dog';
      }
      Dog.prototype = new Animal();

      //创建实例
      var doge = new Dog();
      console.log(doge.name) //'dog';
      doge.say() //'Animal here';
      console.log(doge instanceof Dog) // true
      console.log(doge instanceof Animal) // true

    相当于借A肚子生孩子,完事拉住孩子和A的手说:我是你爸,你也来自A。好处是解决了实例继承的问题,坏处嘛,就是叫了两遍A。

    • Object.create(proto[, propertiesObject])
      ES5引入,我看着underscore用的主要也是这个办法。
      代码原理解释:
      Object.create = function (parent) {
      function F() {}
      F.prototype = parent;
      return new F();
      };
      不多解释了,至于怎么生,这个我真编不出来了,有点像建个工厂,要生娃的基因给我,出来就是你娃。

    其实说多了,个人觉得重在理解,目标是生娃,至于怎么生,就要看清好处坏处了。

    3. 关于创建对象模式的一点嗑叨

    什么是创建对象模式?(看到模式就犯头疼)额,说人话就是实例化,常见的就是var a = new A()
    以前还小的时候看各种模式什么的,晕头转向,浪费时间也浪费脑力。
    所以推荐先实践(酒肉穿肠过,佛祖心中流)实践多了,就会发现模式不模式,自己平时就在用。
    //其实就是好累好累的,下次再补了

    ---------此处为捡节操分割线----------
    最近面试发现自己表达能力很不行,不知道写出来的博客会不会也整晕别人了== 欢迎举正~

    相关文章

      网友评论

        本文标题:js继承与实例化(个人整理)

        本文链接:https://www.haomeiwen.com/subject/rblbqttx.html