继承实现方式
继承的概念
继承是面向对象编程的核心概念之一,允许一个对象获取另一个对象的属性和方法。在JavaScript中,继承主要通过原型链实现,ES6之后也可以通过class语法糖实现更直观的继承方式。
原型链继承
原型链继承是最基本的继承方式,通过将子类的原型指向父类的实例来实现继承。
function Parent() {
this.name = 'parent';
this.colors = ['red', 'blue'];
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child() {
this.age = 10;
}
// 关键步骤:将Child的原型指向Parent的实例
Child.prototype = new Parent();
const child1 = new Child();
child1.sayName(); // 输出: parent
console.log(child1.age); // 输出: 10
这种方式的缺点是:
- 所有子类实例共享父类实例的引用属性
- 无法向父类构造函数传参
构造函数继承
构造函数继承通过在子类构造函数中调用父类构造函数来实现。
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
function Child(name, age) {
Parent.call(this, name); // 关键步骤:调用父类构造函数
this.age = age;
}
const child1 = new Child('Tom', 10);
console.log(child1.name); // 输出: Tom
console.log(child1.age); // 输出: 10
优点:
- 解决了原型链继承中引用属性共享的问题
- 可以向父类构造函数传参
缺点:
- 无法继承父类原型上的方法
- 每次创建实例都要调用父类构造函数
组合继承
组合继承结合了原型链继承和构造函数继承的优点。
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child(name, age) {
Parent.call(this, name); // 第二次调用Parent
this.age = age;
}
Child.prototype = new Parent(); // 第一次调用Parent
Child.prototype.constructor = Child;
const child1 = new Child('Tom', 10);
child1.sayName(); // 输出: Tom
console.log(child1.age); // 输出: 10
优点:
- 可以继承父类实例属性和原型属性
- 可以传参
- 引用属性不共享
缺点:
- 父类构造函数被调用了两次
原型式继承
原型式继承基于已有对象创建新对象,类似于Object.create()的实现。
function createObject(o) {
function F() {}
F.prototype = o;
return new F();
}
const parent = {
name: 'parent',
colors: ['red', 'blue'],
sayName: function() {
console.log(this.name);
}
};
const child = createObject(parent);
child.name = 'child';
child.sayName(); // 输出: child
ES5中可以直接使用Object.create()实现同样的功能。
寄生式继承
寄生式继承在原型式继承的基础上增强对象。
function createAnother(original) {
const clone = Object.create(original);
clone.sayHi = function() {
console.log('hi');
};
return clone;
}
const parent = {
name: 'parent',
colors: ['red', 'blue']
};
const child = createAnother(parent);
child.sayHi(); // 输出: hi
寄生组合式继承
寄生组合式继承是目前最理想的继承方式,解决了组合继承调用两次构造函数的问题。
function inheritPrototype(child, parent) {
const prototype = Object.create(parent.prototype);
prototype.constructor = child;
child.prototype = prototype;
}
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
inheritPrototype(Child, Parent);
const child1 = new Child('Tom', 10);
child1.sayName(); // 输出: Tom
console.log(child1.age); // 输出: 10
ES6类继承
ES6引入了class语法糖,使继承更加直观。
class Parent {
constructor(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
sayName() {
console.log(this.name);
}
}
class Child extends Parent {
constructor(name, age) {
super(name); // 调用父类构造函数
this.age = age;
}
sayAge() {
console.log(this.age);
}
}
const child1 = new Child('Tom', 10);
child1.sayName(); // 输出: Tom
child1.sayAge(); // 输出: 10
多重继承的实现
JavaScript本身不支持多重继承,但可以通过混入(Mixin)模式模拟。
class A {
methodA() {
console.log('method A');
}
}
class B {
methodB() {
console.log('method B');
}
}
class C {
constructor() {
Object.assign(this, new A());
Object.assign(this, new B());
}
methodC() {
console.log('method C');
}
}
const c = new C();
c.methodA(); // 输出: method A
c.methodB(); // 输出: method B
c.methodC(); // 输出: method C
继承与性能考虑
原型链查找会影响性能,过深的原型链会导致查找时间增加。在性能敏感的场景下,可以考虑将常用方法直接定义在对象上。
function createOptimizedObject() {
const obj = {};
obj.method1 = function() { /* ... */ };
obj.method2 = function() { /* ... */ };
return obj;
}
继承与设计模式
继承在多种设计模式中都有应用,如模板方法模式、装饰器模式等。
// 模板方法模式示例
class AbstractClass {
templateMethod() {
this.operation1();
this.operation2();
}
operation1() {
throw new Error('必须实现operation1');
}
operation2() {
throw new Error('必须实现operation2');
}
}
class ConcreteClass extends AbstractClass {
operation1() {
console.log('具体操作1');
}
operation2() {
console.log('具体操作2');
}
}
const instance = new ConcreteClass();
instance.templateMethod();
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:constructor属性
下一篇:对象拷贝与比较