JavaScript 原型链详解
从前有座山,山上有座庙,庙里有个老和尚在给小和尚讲故事,讲的是 JavaScript 的原型链。
什么是原型链?
在 JavaScript 中,每个对象都有一个原型(prototype),而原型又是一个对象。当你访问一个对象的属性或方法时,如果对象本身没有这个属性或方法,JavaScript 引擎就会沿着原型链去查找,直到找到相应的属性或方法或者到达原型链的顶端。
###prototype
和__proto__
在 JavaScript 中,每个函数都有一个特殊的属性叫做 prototype
,而每个对象都有一个特殊的属性叫做 __proto__
。
prototype
是函数特有的属性,指向一个对象,用于存储该函数的原型对象。__proto__
是每个对象(包括函数)都有的属性,指向该对象的原型对象。- 一个对象的
__proto__
指向创建这个对象的构造函数的prototype
。
示例解析
我们来看一个例子:
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
// 创建实例对象
let person = new Person('张三', 25);
// 对象person的__proto__ 等于 构造函数Person的prototype
console.log(person.__proto__===Person.prototype); // true
// Person.prototype也是一个对象,所以Person.prototype也有属性__proto__ ,等于其构造函数Object的prototype
console.log(Person.prototype.__proto__===Object.prototype); // true
// Object.prototype 也是一个对象,但是它已经是最顶层了,所以它的__proto__ 等于 null(不然就没完没了了)
console.log(Object.prototype.__proto__===null); // true
Function 和 Object
// 创建一个函数,其实是 new Function(),所以上面的Person也是一个实例对象,
// Person的构造函数是Function,所以它的__proto__ 等于 Function.prototype
console.log(Person.__proto__===Function.prototype); // true
// 那这么说Function也是一个实例对象,但是它的构造方法就是Function(它也到了最顶层了),
// 所以它的__proto__ 等于 Function.prototype
console.log(Function.__proto__===Function.prototype); // true
// 这么说Object也是一个实例对象,它的构造函数是Function,
// 所以它的__proto__ 等于 Function.prototype
console.log(Object.__proto__===Function.prototype); // true
// 结合上面两个等式,所以有Object.__proto__等于Function.__proto__
console.log(Object.__proto__===Function.__proto__); // true
说到底,之所以会比较绕,其实就是上面的Person,Object,Function 既是一个构造函数,也是一个实例对象。
原型链的应用
原型链的概念可以帮助我们更好地理解 JavaScript 中的继承和属性查找。
// 添加属性到原型对象上
Person.prototype.major = "计算机科学";
Object.prototype.school = "帝国理工学院";
// 访问实例对象的属性
console.log(person.name); // 张三
console.log(person.major); // 计算机科学
// 检查属性是否存在于对象本身
console.log(person.hasOwnProperty('name')); // true
console.log(person.hasOwnProperty('major')); // false
// 检查属性是否存在于原型链上
console.log("major" in person); // true
person对象结构如下:
/**
* person {
* name: '张三',
* age: 25
* __proto__: Person.prototype = {
* major:'cs'
* __proto__: Object.prototype = {
* school:'帝国理工学院'
* __proto__:null
* }
* }
*
*/
总结
JavaScript 的原型链是其特有的一种属性查找机制,通过原型链,我们可以实现对象之间的继承和属性共享。深入理解原型链对于掌握 JavaScript 的核心概念至关重要。