原型、原型链与 ES5 继承:揭开 JavaScript 继承的奥秘
2023-10-11 03:14:50
引子:对象的基石
在 JavaScript 中,一切皆对象。每一个值,无论是简单的数据类型(如数字、字符串、布尔值)还是复杂的数据结构(如数组、对象、函数),都以对象的形式存在。
对象的核心特征之一是拥有一个称为原型的内部属性。原型是一个对象,它包含了与该对象相关的属性和方法的集合。当访问一个对象中的属性或方法时,JavaScript 首先会检查该对象本身。如果没有找到,它会沿着原型链向上查找,直到找到该属性或方法。
原型链:继承的纽带
每个对象都有一个原型,而这个原型的原型又有它自己的原型,以此类推。这种对象与原型之间的链接被称为原型链。原型链允许对象访问其原型及其祖先原型中的属性和方法。
ES5 继承:多种实现
在 ES5 中,继承有几种不同的实现方式,每种方式都具有自己的优势和劣势。
面向对象继承:构造函数的崛起
面向对象继承通过构造函数实现。构造函数是一种特殊的函数,它用于创建新对象。当调用构造函数时,它会创建与构造函数同名的对象,并将其设为新对象的原型。
function Person(name) {
this.name = name;
}
const john = new Person("John Doe");
console.log(john.name); // "John Doe"
构造函数继承的优点:
- 简单易懂
- 保持对象的私有属性私有
构造函数继承的缺点:
- 无法继承原型方法
- 每个子类都必须重新定义父类的方法
借用构造函数实现属性继承
借用构造函数实现属性继承通过在子类构造函数中调用父类构造函数来实现。这允许子类继承父类的属性,但无法继承其方法。
function Person(name) {
this.name = name;
}
function Employee(name, salary) {
Person.call(this, name);
this.salary = salary;
}
const john = new Employee("John Doe", 100000);
console.log(john.name); // "John Doe"
console.log(john.salary); // 100000
借用构造函数继承的优点:
- 允许子类访问父类的属性
- 保持私有属性私有
借用构造函数继承的缺点:
- 无法继承原型方法
寄生组合式继承:结合优势
寄生组合式继承结合了面向对象继承和借用构造函数继承的优点。它首先使用面向对象继承创建子类,然后使用借用构造函数继承将父类属性复制到子类。
function Person(name) {
this.name = name;
}
function Employee(name, salary) {
// 面向对象继承
const employee = new Person(name);
// 借用构造函数继承
employee.salary = salary;
return employee;
}
const john = new Employee("John Doe", 100000);
console.log(john.name); // "John Doe"
console.log(john.salary); // 100000
寄生组合式继承的优点:
- 继承父类的属性和方法
- 保持私有属性私有
寄生组合式继承的缺点:
- 相对复杂
结语:继承的艺术
ES5 中的继承是一门艺术,它需要熟练掌握多种技术。通过了解原型和原型链的概念,并灵活运用面向对象继承、借用构造函数继承和寄生组合式继承,我们可以构建复杂的 JavaScript 应用程序。
掌握继承的精髓,让我们驾驭 JavaScript 的强大功能,在代码的世界中创造令人惊叹的成果!