跳到主要内容

JavaScript是怎么样实现继承的?

参考答案:

在JavaScript中,实现继承的主要方式是通过原型链(Prototype Chain)。每个JavaScript对象都有一个指向它的原型(prototype)的链接。当试图访问一个对象的属性时,如果它自身没有这个属性,那么JavaScript会在它的原型上寻找这个属性,这就是原型链。

在JavaScript中,构造函数(Constructor)和原型(Prototype)是实现继承的两个关键部分。

下面是一个简单的JavaScript继承示例:

// 定义父类
function Parent(name) {
    this.name = name;
    this.play = [1, 2, 3];
}

Parent.prototype.getName = function() {
    return this.name;
}

Parent.prototype.hello = function() {
    console.log('Hello, I am ' + this.name);
}

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

// 让子类继承父类的原型
Child.prototype = Object.create(Parent.prototype);

// 修复构造函数指向
Child.prototype.constructor = Child;

// 添加子类特有的方法
Child.prototype.sayAge = function() {
    console.log('My age is ' + this.age);
}

// 创建一个子类实例
var child = new Child('Tom', 10);

console.log(child.getName());  // Tom
child.hello();  // Hello, I am Tom
child.sayAge();  // My age is 10

// 修改父类原型上的属性,子类实例也会受到影响
Parent.prototype.play.push(4);
console.log(child.play);  // [1, 2, 3, 4]

这个例子中,Child类继承了Parent类,并且添加了自己特有的方法sayAge。通过Object.create(Parent.prototype)Child的原型指向了Parent的一个实例,这样Child就可以访问Parent的原型上的属性和方法了。然后通过Child.prototype.constructor = Child,修复了构造函数的指向,使得new Child()能够正确返回Child的实例。

需要注意的是,由于JavaScript中的对象属性查找是通过原型链实现的,所以如果父类的原型上的属性被修改,那么所有子类的实例都会受到影响,这就是所谓的原型链污染。因此在实际开发中,需要尽量避免直接修改原型上的属性,特别是引用类型的属性。

除了通过原型链实现继承,ES6还提供了classextends关键字来更方便地实现继承。使用classextends的语法糖,可以更方便地创建类和实现继承,但是底层原理仍然是基于原型链的。