JavaScript的原型

对象的原型和构造函数的prototype是两个不同的概念;前者是每个实例上的都有的属性,后者是构造函数的属性。(MDN的解释)

以例子进行解读:

function doSomething(){
    
}
doSomething.prototype.foo = "bar"; 
var doSomeInstancing = new doSomething();
doSomeInstancing.prop = "some value"; 
console.log( doSomeInstancing );
​
<--  这个里面的__proto__就是控制台的[[Prototype]]
{
    prop: "some value",
    __proto__: {
        foo: "bar",
        constructor: ƒ doSomething(),
        __proto__: {
            constructor: ƒ Object(),
            hasOwnProperty: ƒ hasOwnProperty(),
            isPrototypeOf: ƒ isPrototypeOf(),
            propertyIsEnumerable: ƒ propertyIsEnumerable(),
            toLocaleString: ƒ toLocaleString(),
            toString: ƒ toString(),
            valueOf: ƒ valueOf()
        }
    }
}
-->
上述例子可以看出:
doSomeInstancing` 的 `__proto__` 属性就是`doSomething.prototype。(截图)

上述总结:对象需要通过__proto__进行获取原型也就是构造函数的成员;也就是说对象是通过__proto__进行访问原型,构造函数是通过prototype进行访问。

当你访问 `doSomeInstancing` 的一个属性, 浏览器首先查找 `doSomeInstancing` 是否有这个属性. 如果 `doSomeInstancing` 没有这个属性, 然后浏览器就会在 `doSomeInstancing` 的 `__proto__` 中查找这个属性(也就是 doSomething.prototype). 如果 doSomeInstancing 的 `__proto__` 有这个属性, 那么 doSomeInstancing 的 `__proto__` 上的这个属性就会被使用. 否则, 如果 doSomeInstancing 的 `__proto__` 没有这个属性, 浏览器就会去查找 doSomeInstancing 的 `__proto__` 的 `__proto__` ,看它是否有这个属性. 默认情况下, 所有函数的原型属性的 `__proto__` 就是 `window.Object.prototype`. 所以 doSomeInstancing 的 `__proto__` 的 `__proto__` (也就是 doSomething.prototype 的 `__proto__` (也就是 `Object.prototype`)) 会被查找是否有这个属性.(截图)

 

如果没有在它里面找到这个属性, 然后就会在 doSomeInstancing 的 `__proto__` 的 `__proto__` 的 `__proto__` 里面查找. 然而这有一个问题: doSomeInstancing 的 `__proto__` 的 `__proto__` 的 `__proto__` 不存在. 最后, 原型链上面的所有的 `__proto__` 都被找完了, 浏览器所有已经声明了的 `__proto__` 上都不存在这个属性,然后就得出结论,这个属性是 `undefined`.

 

注意:prototype属性包含(指定)一个对象,这个对象中定义了需要被继承的成员。

再说一下constructor属性

每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。(下图需配合构造器函数Person进行观察)

 

 

总结:首先对象是通过new进行创建,所以对象的原型是指构造函数上的成员。构造函数的原型(prototype)指的是通过prototype进行设置的成员,而且最重要的是构造函数的原型默认会有constructor属性。

 

 

这幅图中"fe."之后出来的都是构造函数中的成员,所以对象的原型是指构造函数的成员。第二幅图也可以看出如果没有给构造函数的原型(prototype)设置方法成员就只有一个默认的constructor属性。

进而我们知道,prototype(原型)是构造函数的一个属性,他下面的成员则是这个构造函数拥有的方法和属性;对象的原型是指new的那个构造器函数中的成员。

原型链的话是指通过proto这个方法进行递归的查询对象,构造函数是通过prototype进行查询,是否拥有某方法或属性,proto最后会查到Object,如果没有查到就会返回undefined。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值