JavaScript的继承方式主要包括以下几种:
1. 原型链继承 (Prototype Chain Inheritance)
原型链继承是JavaScript最基本的继承方式。每个JavaScript对象都有一个原型(prototype
),对象从其原型继承属性和方法。创建子类时,将子类的原型设置为父类的实例,从而实现继承。
javascriptfunction Parent() { this.parentProperty = true; } Parent.prototype.getParentProperty = function() { return this.parentProperty; }; function Child() { this.childProperty = false; } Child.prototype = new Parent(); // 设置Child的原型为Parent的实例 Child.prototype.constructor = Child; // 修正constructor指向 var childInstance = new Child(); console.log(childInstance.getParentProperty()); // true
原型链继承存在的问题包括:创建子类实例时不能向父类构造函数传参,而且所有实例共享父类构造函数中的引用属性。
2. 构造函数继承 (Constructor Inheritance)
构造函数继承使用父类构造函数来增强子类实例,通过 call
或 apply
方法在子类构造函数中调用父类构造函数。
javascriptfunction Parent(name) { this.name = name; this.colors = ['red', 'blue', 'green']; } function Child(name) { Parent.call(this, name); // 子类构造函数中调用父类构造函数 } var childInstance = new Child('ChildName'); console.log(childInstance.name); // ChildName
这种方式允许不同的子类实例有不同的属性。不过,它无法继承父类原型上定义的方法,因此不是真正意义上的继承。
3. 组合继承 (Combination Inheritance)
组合继承结合了原型链和构造函数的技术,通过使用原型链继承原型上的属性和方法,使用构造函数继承实例属性。
javascriptfunction Parent(name) { this.name = name; this.colors = ['red', 'blue', 'green']; } Parent.prototype.sayName = function() { return this.name; }; function Child(name, age) { Parent.call(this, name); // 借用构造函数继承属性 this.age = age; } Child.prototype = new Parent(); // 原型链继承方法 Child.prototype.constructor = Child; var childInstance = new Child('ChildName', 18); console.log(childInstance.sayName()); // ChildName console.log(childInstance.age); // 18
组合继承弥补了原型链和构造函数继承的不足,然而它也使得父类构造函数被调用两次,造成了一些不必要的性能开销。
4. 原型式继承 (Prototypal Inheritance)
原型式继承是指使用一个已有对象作为新创建对象的原型。ES5引入了 Object.create
方法来实现原型式继承。
javascriptvar parent = { name: 'Parent', sayName: function() { return this.name; } }; var child = Object.create(parent); child.name = 'Child'; console.log(child.sayName()); // Child
这种方式非常简洁,但同样,所有实例会共享引用属性。
5. 寄生式继承 (Parasitic Inheritance)
寄生式继承类似于原型式继承,但是在此基础上可以增加更多属性或方法。
javascriptvar parent = { name: 'Parent', sayName: function() { return this.name; } }; function createAnother(original) { var clone = Object.create(original); clone.sayHi = function() { console.log('Hi'); }; return clone; } var child = createAnother(parent); child.sayHi(); // Hi