• ECMAScript有6种继承方式(实现继承)


    本人对于ECMAScript继承机制有些见解,如果说的不对,敬请赐教~~~~

    继承是OO语言(面向对象)挺好的概念,许多OO语言都支持两种继承方式(接口只继承方法签名、实际继承则继承实际的方法),但是ECMAScript由于没有签名,只支持实现继承。

    1、原型链继承

    就是一个引用类型继承另一个引用类型的属性和方法。简单回顾下构造函数、原型和实例的关系,每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。如果我们让一个原型对象等于另一个类型的实例,显然,此时的原型对象将要包含另一个原型的指针,相对的,另一个原型中也包含着一个指向另一个构造函数的指针,另一个原型又是另一个类型的实例,如此层层递进,就构成了原型的链条,这就是原型链的概念。

    实现原型链有一种基本模式,如下

    function Father(){
      this.property = true;  
    }
    Father.prototype.getFatherValue = function(){
      return this.property;      
    }
    function Son(){
      this.property = false;  
    }
    //继承了Father
    Son.prototype = new Father();
    Son.prototype.getSonValue = function(){
      return this.property;  
    }
    var instance = new Son();
    alert(instance.getFatherValue()); //true
    

      先从实例中查找属性和方法,如果找不到,在从实例的原型中查找(原型property   原型链 __proto__);

    上面的其实是Son继承了Father,而继承则是通过创建Father的实例,并将该实例赋给Son.prototype实现的,实现的本质就是重写原型对象,代之一个新类型的实例。

    上面的代码没有使用Son默认的原型,而是给他换一个新原型,这个新原型就是Father的实例,所以新原型不但具有作为一个Father的实例所有的属性和方法,而且内部还有一个内部指针,指向Father的原型。故instance指向Son的原型,Son的原型有指向Father的原型,但是getFatherValue()方法仍然存在Father.property中,但是property则位于Son.property中,而getFatherValue()是一个原型的方法,Son.property是property的实例,那么property就位于该实例中。注意:intance.constructor现在指向的是Father,这是因为Son.property中的constructor被重写的缘故。

    查找的步骤:1、搜索实例,2、搜索Son.property,3、搜索Father.property; (原型链是Object,),如果最后还是没有找到,那就是underfined或是null。

    1、默认的原型

    所有的函数的默认原型都是Object的实例,因此默认原型都会包含一个内部指针,指向Object.property,这就是所有自定义类型都会继承toString()、valueOf()等默认方法的根本原因。当你调用instance.toString()就是调用Object.toString()。

    2、确定原型和实例的关系

    第一种方式是 使用 instanceOf操作符 来测试 实例与原型链中出现的构造函数

    alert(instance instanceOf Object); //true
    alert(instance instanceOf Son); //true
    alert(instance instanceOf Father); //true

    第二种方式 是使用 isPrototypeOf() 只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型

    alert(Object.prototype.isPrototypeOf(instance)); //true
    alert(Son.prototype.isPrototypeOf(instance)); //true
    alert(Father.prototype.isPrototypeOf(instance)); //true

    3、谨慎使用定义的方法

    function Father(){
      this.property = true;  
    }
    Father.prototype.getFatherValue = function(){
      return this.property;      
    }
    function Son(){
      this.property = false;  
    }
    //继承了Father
    Son.prototype = new Father();
    //添加新的方法
    Son.prototype.getSonValue = function(){
      return this.property;  
    }
    //重写超类型的中的方法
    Son.prototype.getFatherValue = function(){
        return false;
    }
    var instance = new Son();
    alert(instance.getFatherValue()); //false

    第一个方法getSonValue()被添加到Son中,第二个方法getFathervalue()是原型链中已经存在的,但是后来重写了这个方法,屏蔽原来的那个方法,换句话讲,就是Son的实例调用getFatherValue()时,调用的就是重新定义的方法,但是用Father的实例仍然会调用原来的那个方法,需要注意的是,必须是用Father的实例替换原型后,再定义这两个方法。

    注意:不能使用字面量创建原型方法,因为这样就会重写原型链

    function Father(){
      this.property = true;  
    }
    Father.prototype.getFatherValue = function(){
      return this.property;      
    }
    function Son(){
      this.sonproperty = false;  
    }
    //继承了Father
    Son.prototype = new Father();
    
    //使用字面量添加新方法,会导致上一行代码无效
    Son.prototype.getSonValue = function(){
         getSonValue: function(){
            return this.sonproperty;
        },
        someOtherMethod: function(){
             return false;
        }
    }
    var instance = new Son();
    alert(instance.getFatherValue()); //error

     会出现error,就是因为,使用字面量就是把Son和Father之间的关系切断了。

    4、原型链的问题

  • 相关阅读:
    nginx设置缓存策略
    http缓存原理理解
    promise教程
    vue项目发布到github演示
    vue路由嵌套子路由不渲染
    hihocoder 1403 1407 1415 后缀数组*3 最长公共子串/最长不重叠重复出现的子串/最长k次重复子串
    hdu 4691 后缀数组+rmq 求子串lcp
    hdu1506+ luogu 1440 单调栈/单调队列裸题
    codeforces 873F 后缀数组+单调栈(fastio)
    HihoCoder
  • 原文地址:https://www.cnblogs.com/shirly77/p/6648971.html
Copyright © 2020-2023  润新知