JavaScript 类继承


JavaScript 类继承

JavaScript是一种基于原型的语言,并没有传统的类继承方式。但是原型继承是一种非常强大的方式,可以实现类似于传统面向对象编程中的类继承。

原型链

在JavaScript中所有的对象都有一个原型。原型的属性和方法可以被对象继承,并且对象可以通过原型链链接到其原型。当一个对象的属性或方法在它的原型上没有找到时,JavaScript引擎会到该对象的原型链中寻找,直到找到一个匹配的属性或方法或者到达原型链的顶端。这就是原型链继承的工作原理。

原型继承

原型继承的实现就是在创建一个新对象时,把这个对象的原型设置为一个父对象。在使用这个新对象前,我们可以向它的原型上添加属性和方法,从而可以在新对象上直接访问这些属性和方法。这种继承方式特别适用于共享方法等情况。

下面是一个实现原型继承的示例代码:

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

function Child() {
    Parent.call(this, "child");
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var child = new Child();
console.log(child); //Child { name: "child" }
console.log(child.getName()); //"child"

在代码中我们有一个父类Parent和一个子类Child。首先创建了Parent类,然后在它的原型上添加了一个getName方法。接着创建了Child对象,并将它的原型设置为Parent的实例,这个实例还做了一个唯一性的初始化——Child.prototype.constructor = Child。最后我们创建一个Child实例,验证继承关系并且调用getName方法。

原型继承的缺点

原型继承的主要缺点是当原型上的属性或方法发生改变时,所有继承了该原型的对象都会受到影响。例如:

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

function Child() {
    Parent.call(this, "child");
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var child1 = new Child();
var child2 = new Child();

console.log(child1.getName()); //"child"
console.log(child2.getName()); //"child"

Child.prototype.getName = function() {
    return "new name";
}

console.log(child1.getName()); //"new name"
console.log(child2.getName()); //"new name"

这段代码创建了两个Child实例,并且它们都继承了Parent的原型。接着我们通过修改Child原型添加了一个新的方法getName,结果所有的Child实例都受到了影响。

这个问题可以通过使用对象组合而不是原型链继承来解决,下面将简要介绍这种方式。

对象组合

对象组合是一种创建对象的方式,它可以构建新的对象并且将多个对象组合在一起,从而达到代码重用的目的。通常在一个新的对象上添加方法而不是在原型上添加方法。

下面是一个使用对象组合实现继承的示例代码:

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

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

function Child(name) {
    Parent.call(this, name);
    this.age = 10;
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

Child.prototype.getAge = function() {
    return this.age;
};

var child = new Child("child");

console.log(child.getName()); //"child"
console.log(child.getAge()); //10

在这个例子中,我们使用对象组合的方式实现了继承。Parent是父类,并且我们在它的原型上添加了方法getName。Child是子类,并且我们在它的构造函数中调用了Parent,并且在Child的原型上添加了一个新方法getAge。在调用child实例的方法时,getName方法来自Parent的原型,getAge来自Child的原型。

总结

JavaScript支持原型继承,通过设置一个对象的原型为另外一个对象实现了继承。原型继承的主要缺点是当一个对象的原型上的属性或方法发生改变时,所有继承了该原型的对象都会受到影响。对象组合是一种新的创建对象的方式,通过将多个对象组合在一起达到代码重用的目的并且避免了原型继承可能带来的问题。