图解原型链

目录

1
2
3
4
5
基本概念
new操作符干了哪几件事
instanceof
内存图的角度看原型链
总结

之前一直想整理下原型和原型链相关的知识点,无奈公司事情太忙,一直没有来得及整理,作为前端开发js基础的确很重要。
自己也经常反思自身存在的知识盲点。本文从基本概念出发,再从内存图的角度来解释原型链查找的过程,觉得与口头表述原型链相比较而言,这样理解更为深刻,更有利于巩固自己的知识。

1- 基本概念

  • 原型对象:

    1
    2
    每一个函数都有prototype属性,它默认指向Object空对象(即称为原型对象)
    原型对象本身是一个普通对象,它具有constructor属性,指向其构造函数。
  • 原型对象存在的原因:为实例对象共享公共的属性和方法,避免浪费内存

  • 函数对象与实例对象的区别:

    1
    2
    3
    函数对象可以加括号调用,形如fn();而实例对象不可以,
    但两者作为普通对象而言,都可以打点访问设置自身的属性。形如obj.name,fn.name
    函数对象具有的是"prototype"属性,而实例对象具有的是"__prototype__"属性
  • 显式原型对象和隐式原型对象:

    1
    2
    可以简单的理解成函数对象的prototype属性指向的是显式原型对象,实例对象的__prototype__属性指向的是隐式原型对象
    两者指向的是同一个内存地址:Fun.prototype === fun.__prototype__(构造函数的显式原型对象===当前构造函数实例对象的隐式原型对象)
  • 构造函数:

    1
    2
    任何一个函数都可以作为构造函数,只要被new了,就称为构造函数
    只要定义了构造函数,那么这个函数自动具有prototype属性,会初始化一个原型对象,原型对象具有constructor属性指向其构造函数。
  • 实例对象:只要是对象,无论哪种方式生成,都叫实例

    1
    2
    3
    4
    5
    6
    7
    8
    9

    var o1 = {name:’o1’}//Object{name:’o1’}
    var o11 = new Object( {name:’o11’})//Object{name:’o2’}

    var M = function(){this.name:’o2’}
    var o2 = new M();//M{name:’o3’}

    var P = {name:’o3’}
    var o3 = Object.create(P)//Object{}
  • 原型链:

    1
    2
    3
    4
    访问一个对象的属性时,先在自身属性中查找,找到返回
    如果没有, 再沿着__proto__这条链向上查找, 找到返回
    如果最终没找到, 返回undefined
    __proto__这条原型查找链就是原型链: 隐式原型链
  • 作用域链和原型链:a.b,查找a的时候,a是变量,会沿着作用域链进行查找;查找b时,b是属性,会沿着原型链上面查找。

2- new操作符干了哪几件事

  • 一个新的空对象被创建,它继承了foo.prototype
  • 构造函数foo会被执行,同时this会指向这个新实例
  • 若构造函数返回一个对象,那么这个对象会取代new出来的结果。反之,为1空对象。

3- instanceof

  • 表达式: A instanceof B
  • 如果B函数的显式原型对象在A对象的原型链上, 返回true, 否则返回false

4- 图解原型链

blockchain
blockchain
1.代码中含有构造函数Object,Foo以及实例对象foo,它们都是对象,属于引用数据类型,在栈中分别储存了对应的指针,该指针实际上是指向对应堆内存的引用地址。
2.foo.test1();foo堆内存中地址0x567,先从自身查找test1()方法,发现自身有,查找结束。
3.foo.test2();foo堆内存中地址0x567,先从自身查找test2()方法,查找发现没有,会继续沿着原型链 __prototype__向上查找,但是foo.__prototype__指向哪里呢?由于foo.__prototype__===Foo.prototype,且Foo.prototype引用地址0x456,所以foo.__prototype__会指向0x456发现有,查找结束。
4.同理,foo.toString();会从foo.__prototype__.__prototype__查找到Object对象上,toString()为其内置方法,查询结束。

5- 总结

个人觉得原型对象,构造函数(即函数对象),实例对象,原型链这些概念首先要理解清楚,不能搞混了,然后想办法找到它们之间的内在联系,再想办法画下它们之间的关系图,加深理解和记忆。

-------------本文结束感谢您的阅读-------------