前言
在学习 JavaScript 的过程中, 深感这门语言的一些奇葩设定, 在学习 __proto__ 和 prototype 时, 遇到了一些困惑, 思考了挺久也查阅了很多资料, 于是写了这篇博客来记录。
在 JavaScript 中万物皆对象, Object 作为一个基础类型, 其他是引用继承 Object 而来, 所以每个对象都有一个 __proto__ 属性,但 prototype 是只有函数才有的属性
prototype (显式原型)
先说说 prototype, 几乎所有函数在创建的时候, 会有一个叫 prototype 的属性(通过 Function.prototype.bind 方法构造出来的函数是个例外,它没有 prototype 属性), 这是一个指针, 指向函数的原型对象。 而这个原型对象是用来实现基于原型的继承与属性的共享, 可以让所有对象实例共享它所包含的属性和方法。也就是说不必在构造函数中定义对象实例的信息, 而是添加在原型对象中。
__proto__ (隐式原型)
对象具有 __proto__ 属性, 也就是隐式原型, 这个属性也是指针, 指向该对象的构造函数的显式原型。 隐式原型的作用是构成原型链,同样用于实现基于原型的继承。比如,当我们访问obj这个对象中的x属性时,如果在obj中找不到,那么就会沿着proto依次查找。
1 | // __proto__ 指向该对象的构造函数的 prototype |
上面的代码中 .proto === .constructor.prototype 结果为 true, 但这也不是一定的。 如函数的prototype属性被瞎改的话, 或者如果一个对象是通过Object.create函数构造出来的,那其__proto__就不是.constructor.prototype了。
既然是对象都有 __proto__ 属性, 那么原型对象的 __proto__ 又指向谁呢?
1 | // Object.prototype 的 __proto__ 属性指向 null |
总结
1.对象有属性__proto__,指向该对象的构造函数的原型对象。
2.方法除了有属性__proto__,还有属性prototype,prototype指向该方法的原型对象。
3.Object.prototype 的 __proto__ 属性指向 null。