深入理解js原型和原型链(prototype chain)

深入理解js原型和原型链(prototype chain)

这篇文章不能让你理解他们的底层是如何实现的,但可以让你知道这些属性是什么,有什么用,谁与其关联

  • 首先要知道的概念

    • js 万物皆对象
    • 内置类型:null,undefined,boolean,number,string,symbol,object 拓展资料1 拓展资料2
      • 引用类型Object:Array ,Function, Date, RegExp等
      • 基本类型:null,undefined,boolean,number,string,symbol
    • 原型
      • 隐式原型:所有引用类型,也可以认为是当前带有__proto__属性的对象,他们带有的这个__proto__属性就是该对象的原型。
      • 显示原型:所有函数拥有prototype属性(显式原型)(仅限函数)
      • 原型对象(构造函数):拥有prototype属性的对象,在定义函数时就被创建
    • 引用属性或调用方法
      • 1.对象自身:debug查看该属性时,不是在该对象原型上的属性,而是在最外层的属性
      • 2.当调用某种方法或查找某种属性时,首先会在自身调用和查找,如果对象自身并没有该属性或方法,则会去它的原型__proto__属性中调用查找,如果__proto__中还有__proto__,那么会继续查找,直到最顶级顶级原型。
    • 实例化
      • 1.实例化实际上是将 函数(构造函数)实例化成为一个实例对象,实际实例化的是构造函数的prototype属性,并将其实例化到实例对象的__proto__原型上
      • 2.由上面一条可得知:实例对象想要调用函数的方法,需要将函数的方法定义在函数的prototype属性上【或者定义在函数体内(此种是function所特有的)】
      • 实例对象:将函数(构造函数)new出来. 并且实例对象.proto === 构造函数.prototype,我们也可以通过该式子判断实例对象的构造函数是不是它【因为<实例化-1.>】
    • 构造函数
      • 1.所有函数,诸如class aa {}的aa,function aa{}, Function,Array等,都称作构造函数,并且 String === String.prototype.constructor === String.prototype.constructor.prototype.constructor // true
    • 原型链
      • 1.js所有函数(方法function),类(class),的原型链顶级原型都是Object,二级都是Function
      • 2.通过__proto__构成的原型链,而非prototype
      • 3.如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overiding)
      • 4.一级级向上在原型链寻找某个属性,对性能是有影响的。所寻找的属性在越上层的原型对象,对性能的影响越大。如果寻找某个不存在的属性,将会遍历整个原型链
        可以参考下面这张图理解原型链,当然最好还是自己debug看一下就明白了
        avatar
        avatar
    • 继承
      • 伪继承
  • 举例

    • 引用属性或调用方法
      // 对象自身
      function A(){ this x = 1; }
      A.prototype.s = 2;
      const a = new A();
      // debug查看a:A: { x: 1 }, a.x = 1; 这个x就是自身属性。
      // a中还有原型__proto__: { s: 2 }, 这个s就是原型上的属性,实际就是继承自构造函数A.prototype的属性
    
    • 实例化
      function A(){
        this.id = 1; // 将A函数实例化为实例对象之后自身才会有该属性: A {id: 1}
      }
      A.prototype.id2 = 2; // 不用实例化,自身就带有的属性,通过A.prototype.id2可以访问其属性
      // 此时实例对象na就相当于“继承”了构造函数A的prototype属性,并将A函数内部的id属性添加到自身。
      // 得到如下 A {id: 1}, 隐式原型__proto__:{ id2: 2 },实际就是 A { id: 1, __proto__:{ id2: 2 } }
      const na = new A(); 
    
    • 原型链
    /**
     * 这里有一点需要注意!<原型链1.>【Object函数同样也是Function的实例对象】,但最终原型链最顶级都是* Object。
     * 原型链顶级Object和此处的Object函数通过查看Object函数的__proto__原型可以查看出之间的不同处
     * Object函数包括<对象自身>携带的方法属性,而顶级Object不包含对象自身的方法就是最原始的Object,不带那些方法。
     * 这应该是因为所有的函数都继承于Object,又由于<引用属性或调用方法2.><实例化1.>,所以为了不让所有函数都“继承”Object的方法,就定义在了对象自身。
     **/
     /**
      * Object与Function之间的“继承”关系
      1. Function.__proto__.__proto__ === Object.prototype // true
      Function.__proto__.__proto__.constructor === Object  // true
      2. Object.__proto__.constructor === Function // true, function是Object的构造函数
      而是1. Object.prototype === Function.prototype.
      **/
      // 1. 通过debug查看Object, Number。。。等的__proto__属性,一级一级点开发现最后两级的原型都是function(){ [native code] }和Object
      Int16Array.prototype
      Int32Array.prototype
      Function.prototype.f = "function";
      Object.prototype.o = "object";
      String.prototype.s = "string";
      Number.prototype.n = "number";
      Boolean.prototype.b = "boolean"
      Array.prototype.a = "array"
      Date.prototype.d = "date"
      function Person(){}
      // 由于<原型链的1.>以及<引用属性或调用方法的2.>以及<实例化的1.>,也就是说Number相当于Function的实例对象,而
      console.log(Number.o); // object
      console.log(Number.f); // function
      console.log(Number.n); // undefiend
    
    • 构造函数
      String.prototype.s = "string";
      String === String.prototype.constructor
      String === String.prototype.constructor.prototype.constructor // true
      // 通过任意引用类型对象 原型上的constructor属性可以拿到,他的构造函数
      function A(){ this x = 1; }
      const a = new A();
      a.__proto__.constructor === A; // true
      // 通过任意引用类型对象(对象自身带prototype属性)上的constructor属性,可以拿到他自己
      String.prototype.constructor = String // true
    
    

参考资料1
参考资料2[其中有一处问题,原型链是隐式原型__proto__构成的原型链,最后到get __proto__值为null结束,和prototype无关]
参考资料3

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值