返回

深入浅出理解Javascript原型与原型链,掌握面向对象精髓

前端

原型和原型链:理解 JavaScript 面向对象编程的关键

作为 Web 开发领域的基石,JavaScript 以其灵活性和通用性而闻名。它不仅可以用作脚本语言,还可以用于构建动态 Web 应用程序和交互式用户界面。在 JavaScript 的浩瀚世界中,原型和原型链的概念对于理解其面向对象编程至关重要,本文将深入探讨这两个概念,帮助你全面掌握 JavaScript 的面向对象精髓。

构造函数:实例的蓝图

在 JavaScript 中,函数不仅仅是用来执行代码块的指令,还可以用作构造函数。当一个函数作为构造函数时,通过使用 new 操作符调用它就会创建一个新的对象,这个对象被称为该构造函数的实例。实例就像建筑蓝图,它包含了与构造函数相关联的数据和方法,为具体的对象提供了一个模板。

例如,考虑一个名为 Person 的构造函数,它负责创建带有 name 属性的对象:

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

使用 new 操作符调用 Person 构造函数时,它会创建一个 Person 实例,如下所示:

const person1 = new Person('John Doe');

person1 现在是一个 Person 实例,它拥有 name 属性,并包含 "John Doe" 值。

原型:实例的共享特性

每个构造函数都有一个特殊的属性,称为 prototypeprototype 属性指向一个对象,该对象包含着该构造函数所有实例共有的属性和方法。这就好比一个共享库,其中存储着所有实例都可以访问的通用信息。

对于我们的 Person 构造函数,prototype 对象最初是一个空对象:

console.log(Person.prototype); // {}

然而,我们可以向 prototype 对象添加属性和方法,让所有 Person 实例都能使用它们。例如,我们可以添加一个 greet 方法:

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name}.`);
};

现在,所有 Person 实例都可以调用 greet 方法:

person1.greet(); // 输出: "Hello, my name is John Doe."

原型链:继承的阶梯

每个对象都有一个 __proto__ 属性,指向它的原型对象。对象的 __proto__ 属性指向的原型对象,又称作该对象的原型。这形成了一个原型链,它就像一个继承的阶梯,允许对象访问其祖先的属性和方法。

console.log(person1.__proto__); // { name: 'John Doe', greet: [Function] }

可以看到,person1__proto__ 属性指向 Person.prototype 对象,其中包含了 greet 方法。

继承:祖先的遗产

JavaScript 中的继承是通过原型链实现的。当一个构造函数的 prototype 对象指向另一个构造函数的 prototype 对象时,我们就说前者继承了后者。

例如,创建一个 Student 构造函数,它继承自 Person 构造函数,并增加了 age 属性:

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

Student.prototype = new Person();

现在,Student 构造函数继承了 Person 构造函数的所有属性和方法,并且还增加了自己的 age 属性。

委托:向上寻求帮助

当一个对象访问一个不存在的属性或方法时,JavaScript 会沿着原型链向上查找,直到找到该属性或方法。这个过程称为委托。这就好比一个员工向其主管寻求帮助,如果主管也没有答案,主管会继续向上级寻求帮助,直到找到答案。

const student1 = new Student('Jane Doe', 20);
console.log(student1.name); // "Jane Doe"
console.log(student1.age); // 20
console.log(student1.greet()); // "Hello, my name is Jane Doe."

在上面的例子中,student1 对象没有 greet 方法,但是它的原型(Student.prototype)有。因此,JavaScript 沿着原型链向上查找,找到了 greet 方法并执行它。

属性与方法:实例与原型

对象的属性和方法可以分为两类:实例属性和实例方法,以及原型属性和原型方法。

  • 实例属性和实例方法 属于对象本身,只有该对象本身可以使用。
  • 原型属性和原型方法 属于原型对象,所有继承自该原型对象的实例都可以使用。

总结:原型和原型链的威力

原型和原型链是 JavaScript 中面向对象编程的基础概念。通过原型链,我们可以实现继承、委托、属性和方法的共享等功能。掌握原型和原型链的知识,对于理解 JavaScript 中的面向对象编程至关重要。

常见问题解答

1. 什么是构造函数?
答:构造函数是用于创建新对象的函数,它充当对象的蓝图。

2. 什么是原型?
答:原型是一个对象,它包含了构造函数所有实例共有的属性和方法。

3. 什么是原型链?
答:原型链是一系列通过 __proto__ 属性链接在一起的对象,它允许对象访问其祖先的属性和方法。

4. JavaScript 中是如何实现继承的?
答:JavaScript 中的继承是通过原型链实现的,当一个构造函数的原型指向另一个构造函数的原型时,前者就会继承后者。

5. 什么是委托?
答:委托是当一个对象访问一个不存在的属性或方法时,JavaScript 会沿着原型链向上查找,直到找到该属性或方法的过程。