原型与原型链
JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象。
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
准确地说,这些属性和方法定义在 Object 的构造器函数(constructor functions)之上的 prototype 属性上,而非实例对象本身。
原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链(prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
在对象实例和它的构造器之间建立一个链接(它是 __proto__ 属性,是从构造函数的 prototype 属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法。
一段直观示例
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function () {
console.log('hi, ' + this.name);
};
const p = new Person('Tom');
p.sayHi(); // hi, Tom
// 关键链路:
// p -> Person.prototype -> Object.prototype -> null
console.log(p.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
补充:几个常被问到的细节点:
obj.__proto__只是Object.getPrototypeOf(obj)的 getter,生产环境推荐使用后者。- 所有函数的
__proto__都指向Function.prototype,所有数组的__proto__都指向Array.prototype。 Object.create(proto)可以创建一个以proto为原型的对象,常用来做原型式继承。- 修改
Array.prototype等内置对象原型是危险的,会影响所有同类型实例(慎用,多见于 polyfill)。
来源整理自:vue3js.cn 面试官系列



