返回

构造函数与原型链的深入理解

前端

理解构造函数和原型链是学习JavaScript中面向对象编程的基础。

构造函数

构造函数是一种特殊的函数,用于创建对象。构造函数与普通函数的区别仅在于调用它们的方式不同,任何函数,只要通过new操作符来调用,那它就可以作为构造函数;任何函数,如果不通过new操作符来调用,那么它就是一个普通函数。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

上面的代码定义了一个构造函数Person,它有两个参数:name和age。当我们使用new操作符调用Person构造函数时,它会创建一个新的对象,并将name和age参数作为该对象的属性。

const person1 = new Person('John', 30);
const person2 = new Person('Mary', 25);

上面的代码创建了两个Person对象,person1和person2。person1的name属性为'John',age属性为30;person2的name属性为'Mary',age属性为25。

原型

每个构造函数都拥有一个prototype属性,它指向一个对象。这个对象被称之为原型。原型包含了一些与该构造函数相关的方法和属性。

console.log(Person.prototype);
// 输出: {constructor: ƒ}

上面的代码输出Person的原型对象。我们可以看到,Person的原型对象只有一个属性:constructor,它指向Person构造函数本身。

原型链

原型链是一条从一个对象指向其原型的链。每个对象都有一个原型,而原型的原型又指向另一个原型,以此类推,直到最终指向null。

console.log(person1.__proto__); // 输出: Person.prototype
console.log(Person.prototype.__proto__); // 输出: Object.prototype
console.log(Object.prototype.__proto__); // 输出: null

上面的代码输出person1、Person.prototype和Object.prototype的原型对象。我们可以看到,person1的原型是Person.prototype,Person.prototype的原型是Object.prototype,而Object.prototype的原型是null。

原型链让我们能够访问父对象的方法和属性。例如,person1可以访问Person.prototype中的方法和属性,也可以访问Object.prototype中的方法和属性。

实例的属性和方法

当我们使用new操作符调用一个构造函数时,它会创建一个新的对象,并将构造函数中的属性和方法复制到该对象中。这些属性和方法被称为实例的属性和方法。

console.log(person1.name); // 输出: John
console.log(person1.age); // 输出: 30
person1.sayHello(); // 输出: Hello, my name is John

上面的代码输出person1的name属性和age属性的值,并调用person1的sayHello()方法。

原型的属性和方法

当我们访问一个对象的属性或方法时,JavaScript首先会在该对象中查找该属性或方法。如果没有找到,则会沿着原型链向上查找,直到找到该属性或方法,或者到达null。

console.log(person1.toString()); // 输出: [object Object]

上面的代码输出person1的toString()方法。toString()方法不是person1的实例方法,而是Person.prototype的属性。因此,JavaScript会在person1中查找toString()方法,如果没有找到,则会沿着原型链向上查找,直到在Person.prototype中找到toString()方法。

总结

构造函数、原型和原型链是JavaScript中面向对象编程的基础。理解这些概念对于理解JavaScript的底层机制非常重要。