从一个面试题认识原型链

先亮题

	function D() {}
    D.prototype.proto = "D"
    Function.prototype.func = "Function"
    Object.prototype.obj = "Object"
    var d = new D();
    console.log(d.proto,d.func,d.obj);  // D undefined Object
    console.log(D.proto,D.func,D.obj);  // undefined 'Function' 'Object'
    console.log(Function.proto,Function.func,Function.obj);  // undefined 'Function' 'Object'

先说为什么会是这个结果

console.log(d.__proto__ === D.prototype)  // true
console.log(d.__proto__.__proto__ === Object.prototype)  // true

console.log(D.__proto__ === Function.prototype) // true
console.log(D.__proto__.__proto__ === Object.prototype) // true

这四个等式就解释了d和D查找原型属性的过程,所以得到上面的打印

一、原型属性

1.原型与原型链

每个实例对象(object)都有一个私有属性(称之为__proto__ )指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(即__proto__),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。

上面的话也可以理解为__proto__的作用主要用来指向创建这个对象的函数(构造器:constructor)的prototype,寻找__proto__的关系,直到找到Object的原型对象为null,这就是整个原型链

这段话里面有两个关键的词,__proto__和prototype,推荐大家读一下知乎上的这个问答
可以解释为__proto__即(隐式原型)与prototype(显式原型)
__proto__的作用是作为一个指针指向自己构造函数的原型,而prototype的作用主要是用来实现基于原型的继承与属性的共享

2.怎么去查找原型

实例对象的原型__proto__会指向构造函数的原型对象prototype

console.log(d.__proto__ === D.prototype)  // true
console.log(D.prototype.__proto__ === Object.prototype)  // true

在这里可以清晰的看到从d到原型链顶点的查找过程,其中主要的疑问应该是存在于第二个等式,我们怎么找到D.prototype.__proto__的指向,首先要找到D.prototype是什么

 console.log(D.prototype)
    /* {proto: 'D', constructor: ƒ}
            proto: "D"
            constructor: ƒ D()
            [[Prototype]]: Object
                obj: "Object"
                constructor: ƒ Object()
                hasOwnProperty: ƒ hasOwnProperty()
                isPrototypeOf: ƒ isPrototypeOf()
                propertyIsEnumerable: ƒ propertyIsEnumerable()
                toLocaleString: ƒ toLocaleString()
                toString: ƒ toString()
                valueOf: ƒ valueOf()
                __defineGetter__: ƒ __defineGetter__()
                __defineSetter__: ƒ __defineSetter__()
                __lookupGetter__: ƒ __lookupGetter__()
                __lookupSetter__: ƒ __lookupSetter__()
                __proto__: Object
                get __proto__: ƒ __proto__()
                set __proto__: ƒ __proto__()
    */

D.prototype的原型打印结果是这样的,D.prototype的__proto__属性指向的是Object.prototype。
换一种推论方式也就是D继承自Function,那么依照继承的方式D.prototype = new Function()
,此时问题转换为找内建对象Functionde的实例的__proto__,对于内建对象的原型,几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。由此就得到了上面的等式。

二、NOTE

通过Function.prototype.bind方法构造出来的函数是个例外,它没有prototype属性
console.log(Function instanceof Object) // true
console.log(Object instanceof Function) // true
参看文章:一张图看懂Function和Object的关系及简述instanceof运算符
知识所限,有些地方还是说的不够明白,以后再补充吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霜叶w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值