4、JavaScript 原型与原型链

26 阅读2分钟

JavaScript 原型与原型链

本文档详细介绍了JavaScript中的原型与原型链,以及它们在前端开发中的应用。

概述

JavaScript是一种基于原型的语言,每个对象都有一个原型属性,通过原型链对象之间可以继承属性和方法。利用这个特性,可以实现对象继承和复用。

构造函数与原型

在JavaScript中,每个函数都有一个prototype属性。这个属性是一个对象,所有通过这个函数创建的实例都会共享这个对象上的属性和方法。

示例代码

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

// 在Person的原型上定义一个方法
Person.prototype.sayHello = function() {
    console.log(`Hello, my name is ${this.name}, and I am ${this.age} years old.`);
};

// 创建Person的实例
const person1 = new Person('Alice', 25);
const person2 = new Person('Bob', 30);

// 调用实例方法
person1.sayHello(); // Hello, my name is Alice, and I am 25 years old.
person2.sayHello(); // Hello, my name is Bob, and I am 30 years old.

上述代码展示了如何通过构造函数和原型创建对象并定义共享方法。

原型链

当访问对象的属性时,JavaScript会首先查找对象自身的属性。如果找不到,它会去对象的原型(即__proto__)上查找。这个过程称为原型链。

示例代码

console.log(person1.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true

原型链示意图

person1 -> Person.prototype -> Object.prototype -> null

在上述代码中,person1.__proto__指向Person.prototypePerson.prototype.__proto__指向Object.prototype,而Object.prototype.__proto__null,表示原型链的顶端。

继承

JavaScript的原型链提供了继承的功能。可以通过修改原型链实现对象的继承。

示例代码

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

// 设置Employee的原型为Person的实例
Employee.prototype = Object.create(Person.prototype);

// 纠正Employee的构造函数引用
Employee.prototype.constructor = Employee;

// 在Employee的原型上定义新方法
Employee.prototype.sayJobTitle = function() {
    console.log(`I am a ${this.jobTitle}.`);
};

// 创建Employee的实例
const employee1 = new Employee('Charlie', 28, 'Developer');

// 调用父类和子类的方法
employee1.sayHello(); // Hello, my name is Charlie, and I am 28 years old.
employee1.sayJobTitle(); // I am a Developer.

上述代码展示了如何通过原型链实现继承。

ES6类语法

ES6引入了class关键词,使得定义类和继承更加直观和简洁。

示例代码

// 定义Person类
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    // 定义方法
    sayHello() {
        console.log(`Hello, my name is ${this.name}, and I am ${this.age} years old.`);
    }
}

// 定义Employee类继承Person类
class Employee extends Person {
    constructor(name, age, jobTitle) {
        super(name, age); // 调用父类构造函数
        this.jobTitle = jobTitle;
    }

    // 定义新方法
    sayJobTitle() {
        console.log(`I am a ${this.jobTitle}.`);
    }
}

// 创建Employee实例
const employee1 = new Employee('Dave', 35, 'Designer');

// 调用父类和子类的方法
employee1.sayHello(); // Hello, my name is Dave, and I am 35 years old.
employee1.sayJobTitle(); // I am a Designer.

通过classextends关键字,可以看出ES6提供了更简洁和清晰的语法来定义类和实现继承。