原型以及原型链之旅,不可不探的JS奥秘

2 篇文章 0 订阅

      JS原型以及原型链,一直以来都是重中之重,任何接触过JS这门语法的人,都知道,任何新建的对象之间都存在着继承关系,追根溯源之后都能走到原型链之上,那么什么是原型链,如何使用好原型链呢?

    首先需要知道的一点就是:是不是所有的类型都有原型链?

    从学习JS以来,我们就知道JS中有2大类型,一种是基础类型,一种是引用类型

    基础类型分为:NumberBooleanStringnullundefinedsymbol(ES6中加入)

    引用类型分为ObjectFunction

    首先,在这里先明确一个概念:

          并不是所有的类型都有原型链基础类型没有原型链的,因为基础类型存放在栈中的,比较的时候仅仅就是一个值类型的比较,根本无需追根朔源

          而引用类型有原型链的,因为引用类型引用变量名称存放在栈中(方便快速定位对象内存空间的地址),实际的对象存储空间其实是存储在堆中的。这里其实也可以涉及到浅拷贝和深拷贝的知识点,但由于这里主讲原型链,就先不进行扩展了(当你了解了原型链之后,浅拷贝和深拷贝其实就是被剥了壳的鸡蛋,一览无余)。

        所以说,以后千万不要一说到原型链,就开始泛泛而谈,首先应该明确目标,只有引用类型才有原型链,基础类型是没有原型链的。

        既然对象明确了,那么我们来进行初次接触:

1.当前对象不存在这个属性,但父类存在

      从上图可以看到,打印person对象,会person对象中存在一个__propt__属性,这个属性的值是一个对象,那些或多或少的小伙伴们,如果接触过原型的操作,一定不会陌生如何往原型中注入属性age属性(Object.prototype.age = 18),对比persony原型前后的改变:

        显然,我们并没有直接对person对象进行操作(如使用person.age=18)。在这里我们是对Object这个对象的原型进行操作,可能你会疑惑为什么对Object对象的原型注入的age属性为什么能在person对象上显示出来呢?其实这里就已经涉及到原型链的知识了,且看下图:

       打开这个__proto__这个对象的constructor(构造函数),你就会发现在person对象构造函数的属性中已经添加了age:18,初次接触会感觉多么的神奇,为什么我在Object原型上注入的属性,竟然莫名其妙的跑到了person对象的构造函数上来了。

      这里先给出结论:当新创建了对象(person)后,如果没有在对象上绑定相应属性(如这里的age属性,并没有直接绑定在新创建的person对象上),那么此时的对象person为了获取这个属性,就会去查找构造函数上的propotype属性,(也就是父类的propotype属性(Object.prototype)),请看下图:

        首先,输出person.__proto__属性的内容

        随后打开constructor函数的prototype属性

        最后输出Object的prototype属性,会发现两者都有age这个属性

  2.当前对象不存在这个属性,连父类也不存在

       看到这里上面就可以明白了,如果我们去查找一个对象的属性,但是从当前这个对象无法直接获取的时候,这个时候当前的对象就会通过__proto__属性去查找父类的prototype属性,如果父类的prototype属性仍然找不到,那么这个父类就会继续查找它的父类,直到最顶层的Object对象,如果仍然找不到,那么就为null,此时就会停止查找,然后报错,如下:

        可以看到,如果我们没有在person对象的原型以及父类(Object对象)上添加color属性时,会直接显示undefined;

3.当前对象存在这个属性,父类也存在这个属性

      基于上面的基础,我们在person对象上添加属性age,如下:

          可以看到,如果当前对象(person)上存在这个属性,那么会直接输出绑定在当前对象上的属性值,当然,还有一种情况就是当前对象存在这个属性,但是父类不存在,那么很好理解,既然当前对象都存在这个属性了,必然是不会去通过__proto__属性去查找父类的prototype属性的。

            这里加个例子方便大家了解,如果你(当前对象son)现在没有钱(属性)了,那么就去找你爸爸(Father父类)要钱,如果你爸爸也没钱,就去找你爷爷(Grandpa爸爸的父类)要,如果仍然没有钱,那就哦豁,真的没了(null),图例如下:

        最终总结:查找一个对象的属性值,如果当前对象存在这个属性值,就直接为当前对象的属性值,如果当前对象值不存在这个属性,那么当前对象就默认通过__proto__这个属性去查找父类的prototype属性,如果父类仍然查找不到这个属性,继续往上查找,直到连Object对象也不存在这个属性值,那么就会返回undefined

        小细节:

       为什么值类型没有原型链这个概念?因为值类型连父类都没有,就是表示单纯的值,所以没有__proto__这个属性去通过构造函数查找父类的prototype属性,所以肯定不存在原型链继承这个概念了。

        此外,一定要注意ES6中的箭头函数,因为它没有继承Function函数,因此没有call、apply、bind这类的方法。

          

     

 

     

      

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值