一、概念解释
原型链是JavaScript中对象继承的一种重要方式,其基本概念可以归结为以下几点:
- 原型(Prototype):在JavaScript中,每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
- 隐式原型(proto):每个对象(包括函数对象)都有一个__proto__属性,这个属性是一个指向其构造函数的prototype属性的指针。这个属性是隐式的,通常我们在代码中不会直接访问它,但在理解原型链的过程中它非常关键。
- 构造函数(Constructor):构造函数是一种特殊的函数,用于初始化新创建的对象。在JavaScript中,构造函数通常与new关键字一起使用来创建新的对象实例。
二、原型链的形成
原型链的形成主要基于以下两点:
- 当我们创建一个新的对象实例时,它的__proto__属性会被自动设置为指向构造函数的prototype属性。
- 同时,构造函数的prototype属性本身也是一个对象,它也有自己的__proto__属性。在默认情况下,这个__proto__属性指向Object.prototype(即Object的原型对象)。
这样,通过每个对象的__proto__属性和构造函数的prototype属性,我们可以将多个对象链接起来,形成一个链式结构,这就是原型链。
三、原型链的作用
原型链的主要作用是实现对象的继承。当我们尝试访问一个对象的某个属性或方法时,JavaScript会首先在当前对象本身查找该属性或方法。如果找不到,则会沿着原型链向上查找,直到找到为止。如果在原型链的顶端(即Object.prototype)仍然没有找到,那么就会返回undefined(对于属性)或抛出错误(对于方法)。
四、图解示例
假设我们有以下代码:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log('Hello, my name is ' + this.name);
};
var john = new Person('John', 30);
在这个例子中,john对象的原型链结构可以表示为:
john -> Person.prototype
补充一句,只要是对象就会拥有__proto__属性指向上一级的原型对象
当我们调用john.sayHello()时,JavaScript首先会在john对象本身查找sayHello方法。由于john对象本身没有这个方法,所以会沿着原型链向上查找,最终在Person.prototype上找到了这个方法并执行。
还会出现另外一种情况,就是john调用 john.xxx() 方法,也就是由于john对象本身没有这个方法,john就会通过 __proto__ 指向上一级,也就是 Person.prototype , 如果也不存在这个xxx方法,那么就会沿着原型链一直向上查找,因为Person.prototype也是一个对象,只要是对象就会拥有__proto__,他指向了更上一级,也就是 Object.prototype 最大的原型,如果也没有我们要找的方法,Object.prototype也是一个对象,通过对象里的__proto__ 指向更上一级 , 但是我们会发现Object.prototype 的 __proto__ 指向了一个 null,也就是说原型链的终点是 null ,即最顶层的原型对象没有原型
john -> Person.prototype -> Object.prototype -> null。