1. JavaScript原型与原型链概念解析
在学习 JavaScript 的过程中,我们难免会遇到“原型”和“原型链”这两个概念。那么,这两个概念到底是什么呢?
首先,我们需要知道,JavaScript 中的每一个对象都有一个内部属性,称之为原型。该原型可以是另一个对象或 null。如果该原型是另一个对象,则该原型又有自己的原型,这样一层层连接下去,就得到了所谓的原型链。
换句话说,每个 JavaScript 对象都有一个 __proto__
内部属性,该属性指向该对象的原型对象。而原型对象又有自己的 __proto__
属性,指向自己的原型对象,直到指向为 null 为止。
2. 构造函数和原型对象
2.1 构造函数
在 JavaScript 中,对象是通过构造函数来创建的。在创建对象的过程中,构造函数扮演了至关重要的角色。
我们先来看一个示例:
function Person(name) {
this.name = name;
}
const person = new Person('Tom');
console.log(person.name); // 输出 'Tom'
在上面的代码中,我们定义了一个叫做 Person 的构造函数,并在该函数中指定了一个属性 name。接着,我们使用 new 运算符来创建一个 person 对象,最后再输出 person.name 属性,可以看到输出的结果是 'Tom'。
2.2 原型对象
在上面的示例中,我们创建了一个 person 对象,但是它的内部到底是如何保存该对象的属性的呢?这就与原型对象息息相关了。
我们可以为构造函数指定一个原型对象,这样所有由该构造函数创建的对象,都会有一个共同的原型。在 JavaScript 中,我们可以使用 Object.create()
方法来创建一个对象,并指定该对象的原型。
下面是一个示例代码:
function Person(name) {}
Person.prototype.name = 'Tom';
const person1 = new Person();
const person2 = new Person();
console.log(person1.name); // 输出 'Tom'
console.log(person2.name); // 输出 'Tom'
在上述示例中,我们没有为 person1 和 person2 指定属性 name,而是在构造函数 Person 的原型中指定了该属性。这样一来,由构造函数创建出来的对象,均可尝试访问该属性。如果该属性不存在该对象中,它就会一层一层地向上查找原型链,直到找到该属性或是查找到 null 为止。
3. 原型链
了解了构造函数和原型对象的概念之后,接下来我们来看一下原型链是如何形成的。
在 JavaScript 中,每个对象都有一个内部链接,称之为 [[Prototype]](注意这是内部链接,不是我们在代码中访问的 __proto__
属性)。该链接指向它所对应的原型对象。
换句话说,当我们需要访问一个对象的属性或是方法时,如果该属性或方法并不存在于该对象本身,则它就会去对象的原型对象中寻找。如果还没有找到,它就会一层一层地向上查找原型链,直到找到该属性或是查找到 null 为止。
下面让我们来看一个示例,了解原型链的基本运行机制。
function Person(name) {}
Person.prototype.name = 'Tom';
const person = new Person();
console.log(person.name); // 输出 'Tom'
console.log(person.__proto__ === Person.prototype); // 输出 true
console.log(Person.prototype.__proto__ === Object.prototype); // 输出 true
console.log(Object.prototype.__proto__); // 输出 null
在上述示例代码中,我们先创建了一个构造函数 Person,并为该函数指定了原型对象。接着使用该构造函数创建了一个 person 对象,并尝试访问 person.name 属性。在该属性不存在 person 对象中时,它会沿着原型链查找,最终在原型对象 Person.prototype 中找到了该属性。
同时,我们还可以通过 __proto__
属性来访问对象的原型链,从而观察到原型链的形态。在这个过程中,我们可以看到 Person.prototype 的原型对象是 Object.prototype。Object.prototype 是所有对象的祖先,它是原型链的最终 null 值。
4. 总结
JavaScript 中的原型和原型链是一个重要的基础概念。通过学习它,我们能够更好地理解对象的属性、方法以及继承等概念。在实际工作中,我们需要深入理解它的运行原理,才能写出高效、优雅的 JavaScript 代码。