Skip to content

原型与构造函数

在 JavaScript 中,原型(Prototype)和构造函数(Constructor Function)是实现面向对象编程的两个核心概念。理解它们之间的关系和工作原理对于编写高效且结构良好的代码非常重要。

构造函数 (Constructor Function)

构造函数是一种特殊的函数,用于创建和初始化对象实例。构造函数通常与 new 关键字一起使用,以创建具有特定属性和方法的对象。

基本语法

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

创建对象实例

javascript
const alice = new Person("Alice", 30);
console.log(alice); // 输出: Person { name: 'Alice', age: 30 }

原型 (Prototype)

每个函数都有一个 prototype 属性,这是一个对象,包含可以被所有实例共享的方法和属性。通过原型链机制,JavaScript 实现了继承和方法共享。

基本语法

javascript
Person.prototype.greet = function () {
  console.log(
    "Hello, I'm " + this.name + " and I'm " + this.age + " years old."
  );
};

使用原型上的方法

javascript
const alice = new Person("Alice", 30);
alice.greet(); // 输出: Hello, I'm Alice and I'm 30 years old.

原型与构造函数的关系

  1. 原型链

    • 每个对象都有一个内部属性 [[Prototype]](可以通过 __proto__ 访问),指向其构造函数的 prototype 对象。
    • 当访问对象的属性或方法时,如果对象自身没有该属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或方法,或者到达原型链的末端(即 null)。
  2. 构造函数的 prototype 属性

    • 构造函数的 prototype 属性是一个对象,包含可以被所有实例共享的方法和属性。
    • 通过 new 关键字创建的每个对象实例都会隐式地链接到构造函数的 prototype 对象。
  3. constructor 属性

    • prototype 对象有一个默认的 constructor 属性,指向构造函数本身。
    • 通过这个 constructor 属性,可以知道某个对象是由哪个构造函数创建的。

示例

下面是一个完整的示例,展示了构造函数、原型和原型链的工作原理:

javascript
// 定义构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 在原型上添加方法
Person.prototype.greet = function () {
  console.log(
    "Hello, I'm " + this.name + " and I'm " + this.age + " years old."
  );
};

// 创建对象实例
const alice = new Person("Alice", 30);

// 调用原型上的方法
alice.greet(); // 输出: Hello, I'm Alice and I'm 30 years old.

// 查看原型链
console.log(alice.__proto__ === Person.prototype); // true
console.log(Person.prototype.constructor === Person); // true
console.log(alice instanceof Person); // true

继承

JavaScript 通过原型链实现继承。子类可以继承父类的属性和方法,并且可以添加自己的特有属性和方法。

示例:继承

javascript
// 父类构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 在父类原型上添加方法
Person.prototype.greet = function () {
  console.log(
    "Hello, I'm " + this.name + " and I'm " + this.age + " years old."
  );
};

// 子类构造函数
function Student(name, age, grade) {
  // 调用父类构造函数
  Person.call(this, name, age);
  this.grade = grade;
}

// 设置原型链
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

// 添加子类特有的方法
Student.prototype.study = function () {
  console.log("I'm studying in grade " + this.grade);
};

// 创建子类实例
const alice = new Student("Alice", 30, 10);

// 调用从父类继承的方法
alice.greet(); // 输出: Hello, I'm Alice and I'm 30 years old.

// 调用子类特有的方法
alice.study(); // 输出: I'm studying in grade 10

// 查看原型链
console.log(alice.__proto__ === Student.prototype); // true
console.log(Student.prototype.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null

总结

  • 构造函数 用于创建和初始化对象实例。
  • 原型 是一种对象,包含可以被所有实例共享的方法和属性。
  • 原型链 使得对象可以访问其原型上的方法和属性。
  • 通过设置原型链,可以实现继承,使子类继承父类的属性和方法。

理解构造函数和原型之间的关系以及如何使用它们是掌握 JavaScript 面向对象编程的关键。如果你有更多关于构造函数和原型的具体问题或需要进一步的例子,请告诉我!

Released under the MIT License.