JavaScript 六种常见继承模式详解与对比

作者:木棉时间:2026-10-24 22:20:53浏览:456

本文系统梳理 JavaScript 中六种核心继承机制,涵盖原型链、盗用构造函数、组合继承、原型式、寄生式及寄生组合式继承。深入解析各模式的实现原理、优缺点及适用场景,重点对比引用类型污染与性能开销问题,帮助开发者根据实际需求选择最优继承方案。

前言

JavaScript 是一门高度灵活的语言,实现同一功能通常存在多种路径。ECMAScript 标准并未定义明确的继承机制,而是依赖语言特性进行模拟。基于此,JavaScript 衍生出几种通用的继承实现方式。

温馨提示:本文中Super函数都是指父类,Sub函数都是代表子类。同时文中会涉及到“构造函数模式”和“工厂模式”,如果不熟悉的小伙伴,可以先看看这篇介绍 js常见的4种创建对象方式。

1、原型继承

实现方式如下:

function Super(){ this.a=1 }
Super.prototype.say = function(){ console.log(‘hhh') }
function Sub(){}
Sub.prototype = new Super()

const test = new Sub()
console.log( test.say() )// hhh

优点:允许通过原型链访问多个引用类型的属性和方法。

缺点:Sub 的原型被设置为 Super 的实例。若 Super 的实例属性包含引用值,该引用值将被所有 Sub 实例共享,导致数据污染。示例如下:

function Super(){ this.a=[1,2] }
function Sub(){}
Sub.prototype = new Super()

const test1 = new Sub()
test1.a.push(3)
console.log(test1.a)// [1,2,3]
const test2 = new Sub()
console.log(test2.a)// [1,2,3]

2、盗用构造函数(Constructor Stealing)

实现方式:结合构造函数模式与 call 方法。

function Super = function(){ this.a = 1 }
function Sub = function(){
       Super.call(this)
       this.b = 2
}

const test = new Sub()

优点:每个实例拥有独立的 a 属性,即使是引用类型也不会发生共享污染。

缺点:Super 构造函数中的方法必须在每个实例上重新创建(除非该方法定义在全局);此外,Sub 的实例无法访问 Super 原型上定义的方法。

3、组合继承(Combination Inheritance)

实现方式:结合原型继承与盗用构造函数继承。

function Super(){ this.a=[1,2] }
Super.prototype.say = function(){ console.log(‘hhh') }
function Sub(){
    Super.call(this)
    this b=2
}
Sub.prototype = new Super()
 
const test1 = new Sub()
console.log( test1.say() )// hhh
test1.a.push(3)
console.log(test1.a)// [1,2,3]
const test2 = new Sub()
console.log(test2.a)// [1,2]

优点:结合了上述两种模式的优点,既保证了实例属性的独立性,又实现了方法的复用。

缺点:存在效率问题,Super 构造函数会被调用两次。

4、原型式继承(Prototypal Inheritance)

实现方式:

ES5 之前:

const obj = { a:1 }
function createObj(o){
    const Fn(){}
    Fn.prototype = o
    return new Fn()
}

const test = createObj(obj)

ES5 之后:

const obj = { a:1 }

const test = Object.create(obj)

优点:通过浅克隆创建新对象,并继承原对象的原型属性。

缺点:由于采用浅克隆,若实例共享的对象属性为引用值,仍会受到污染。示例如下:

const obj = { a:[1,2], b:2 }
const test1 = Object.create(obj)
const test2 = Object.create(obj)

test1.a.push(3)
test1.b=3
console.log(test1.a, test2.a)// [1,2,3]  [1,2,3]
console.log(test1.b, test2.b)// 3 2

5、寄生式继承(Parasitic Inheritance)

实现方式:结合构造函数模式与工厂模式。

function createObj(o){
    let clone = objectCopy(o)
    clone.say=function(){
        console.log(‘hhh')
    }
    return clone
}

const obj = { a:1 }
const test = createObj(obj)

优点:基于现有对象克隆创建新对象,并可增强对象功能。

缺点:与盗用构造函数类似,方法在每个实例上均需重新创建。

注意:objectCopy 用于复制入参对象。

6、寄生式组合继承(Parasitic Combination Inheritance)

实现方式:结合盗用构造函数继承与原型式继承。

function Super(){ this.a=[1,2] }
Super.prototype.say = function(){ console.log(‘hhh') }
function Sub(){
    Super.call(this)
    this b=2
}

Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub

const test = new Sub()

优点:结合了原型式继承与盗用构造函数继承的优点,且效率高于组合继承。

总结

本文介绍了 JavaScript 中常见的六种继承方式。如需了解更多相关内容,请搜索本站历史文章或继续阅读后续文章。感谢大家的支持!

作者最新文章