美文网首页
关于原型链,__proto__和prototype,继承

关于原型链,__proto__和prototype,继承

作者: xuehairong | 来源:发表于2019-11-14 11:25 被阅读0次

    ES6关于构造函数和继承有了新的语法,但先分析之前的写法,有助于理解原理

    1.原型链

    javascript没有像Java、C#类的概念,要实现继承只能是通过“原型(prototype)”这条链子将要继承的对象链接起来

    //对象
    var o={}
    o.__proto__===Object.prototype//true
    //数组
    var arr=[1,2]
    arr.__proto__===Array.prototype //true
    Array.prototype.__proto__===Object.prototype //true
    Object.prototype.__proto__===null //true
    //函数
    function f(){}
    f.__proto__===Function.prototype//true
    Function.prototype.__proto__===Object.prototype//true
    

    说实话一直困惑__proto__prototype这俩啥关系,通过上面的代码就再清晰不过了__proto__指向了所继承的父原型,prototype指向自己的原型,所以通过修改__proto__可以改变所继承的原型,但__proto__ 并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,虽然目前很多现代浏览器的 JS 引擎中都提供了这个私有属性,但依旧不建议在生产中使用该属性,避免对环境产生依赖。生产环境中,我们可以使用 Object.getPrototypeOf方法来获取实例对象的原型,然后再来为原型添加方法/属性。

    2.构造函数

    function Person(name,age){
      this.name=name
      this.age=age
      this.sayName=function(){
        alert(this.name)
      }
    }
    Person.prototype.constructor===Person//true
    

    以上是个构造函数,我一直觉得就是个函数,但其实它返回的是个对象,用new关键字构造一个对象。并且在自己的prototype上将constructor属性指向了自己

    var person1=new Person('张三',27)
    var person2=new Person('李四',18)
    person1.constructor===Person//true
    person1.__proto__===Person.prototype//true
    person2.__proto__===Person.prototype//true
    person1.sayName===person2.sayName//false 这不是我们想要的
    

    每个实例的属性需要不一样,因为每个人的名字不一样,但是sayName需要共用,可以把需要共用的属性或方法放在prototype上,

    Person.prototype.sayName2=function(){
      alert(this.name)
    }
    person1.sayName2===person2.sayName2//true
    

    现在Person上其实有2个属性,一个是默认生成的constructor,另一个是sayName2,所以又可以用以下的写法解释

    Person.prototype={
      constructor:Person,
      sayName2:function(){
        alert(this.name)
      }
    }
    

    接下来对比以下ES6的新语法class

    class Person{
      constructor(name,age){//放在构造器里面的是 不公用的
        this.name=name
        this.age=age
        this.sayName=function(){
          alert(this.name)
        }
      }
     //放在构造器外面的是公用的
      sayName2(){
        alert(this.name)
      }
    }
    

    咋样,就感觉是把之前的写法合并起来了

    3.继承

    //父构造函数
    function SuperType(name){
      this.name=name
    }
    SuperType.prototype.sayName=function(){
      alert(this.name)
    }
    //子构造函数
    function SubType(name,age){
      SuperType.call(this,name)
      this.age=age
    }
    var sub=new SubType('张三',12)
    sub.name//"张三"
    sub.sayName//undefined
    sub.__proto__===SubType.prototype//true
    SubType.prototype.__proto__===SuperType.prototype//false
    

    先用call方法继承构造器里的属性,此时的关系为,sub——>SubType——>Object,要实现继承要把SubType.prototype.__proto__===SuperType.prototype 你可能想这么写 SubType.prototype = SuperType.prototype,但这样是不行的,他们俩公用一个原型的话,SubType就没有存在的意义了,我们可以用下面的代码

    function F(){}//先创建了一个临时性的构造函数
    F.prototype = SuperType.prototype;//将父原型作为临时构造函数的原型
    var prototype=new F()//这边也可以直接用new SuperType(),但这样加上上面的call方法会导致2次调用SuperType
    prototype.contructor=SubType
    SubType.prototype=prototype//然后将临时构造函数的实例作为子构造函数的原型
    SubType.prototype.__proto__===SuperType.prototype//true
    

    下面来看看ES6继承的写法

    class SuperType{
      constructor(name){
        this.name=name
      }
      sayName(){
        alert(this.name)
      }
    }
    class SubType extends SuperType{
      constructor(name,age){
        super(name)//必须调用下父类
        this.age=age
      }
      sayAge(){
        alert(this.age)
      }
    }
    var sub=new SubType('张三',12)
    sub.__proto__===SubType.prototype//true
    SubType.prototype.__proto__===SuperType.prototype//true
    

    注意这边会多一个联系,这个是ES6特有的

    SubType.__proto__===SuperType//true
    

    这样的结果是因为,类的继承是按照下面的模式实现的。

    class SuperType {
    }
    class SubType {
    }
    // B 的实例继承 A 的实例  B.prototype.__proto__=A.prototype
    Object.setPrototypeOf(SubType.prototype, SuperType.prototype);
    // B 继承 A 的静态属性  B.__proto__=A
    Object.setPrototypeOf(SubType , SuperType );
    

    这两条继承链,可以这样理解:作为一个对象,子类(SubType)的原型(__proto__属性)是父类(SuperType);作为一个构造函数,子类(SubType)的原型对象(prototype属性)是父类的原型对象(prototype属性)的实例。

    相关文章

      网友评论

          本文标题:关于原型链,__proto__和prototype,继承

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