谈谈 JS 中 __proto__ 和 prototype

前言

关系图
在学习 JavaScript 的过程中, 深感这门语言的一些奇葩设定, 在学习 __proto__ 和 prototype 时, 遇到了一些困惑, 思考了挺久也查阅了很多资料, 于是写了这篇博客来记录。


在 JavaScript 中万物皆对象, Object 作为一个基础类型, 其他是引用继承 Object 而来, 所以每个对象都有一个 __proto__ 属性,但 prototype 是只有函数才有的属性


prototype (显式原型)

先说说 prototype, 几乎所有函数在创建的时候, 会有一个叫 prototype 的属性(通过 Function.prototype.bind 方法构造出来的函数是个例外,它没有 prototype 属性), 这是一个指针, 指向函数的原型对象。 而这个原型对象是用来实现基于原型的继承与属性的共享, 可以让所有对象实例共享它所包含的属性和方法。也就是说不必在构造函数中定义对象实例的信息, 而是添加在原型对象中。

__proto__ (隐式原型)

对象具有 __proto__ 属性, 也就是隐式原型, 这个属性也是指针, 指向该对象的构造函数的显式原型。 隐式原型的作用是构成原型链,同样用于实现基于原型的继承。比如,当我们访问obj这个对象中的x属性时,如果在obj中找不到,那么就会沿着proto依次查找。

1
2
//  __proto__ 指向该对象的构造函数的 prototype
console.log(Array.__proto__ === Array.constructor.prototype); // true

上面的代码中 .proto === .constructor.prototype 结果为 true, 但这也不是一定的。 如函数的prototype属性被瞎改的话, 或者如果一个对象是通过Object.create函数构造出来的,那其__proto__就不是.constructor.prototype了。
既然是对象都有 __proto__ 属性, 那么原型对象的 __proto__ 又指向谁呢?

1
2
// Object.prototype 的 __proto__ 属性指向 null
console.log(Object.prototype.__proto__); // null

总结

1.对象有属性__proto__,指向该对象的构造函数的原型对象。
2.方法除了有属性__proto__,还有属性prototype,prototype指向该方法的原型对象。
3.Object.prototype 的 __proto__ 属性指向 null。

------ 本文结束 ------

版权声明

Tflin's Blog by Tan Feng Lin is licensed under a Creative Commons BY-NC-ND 4.0 International License.
谭丰林创作并维护的Tflin's Blog博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Tflin's Blog 博客( http://tflin.com ),版权所有,侵权必究。