面试官的 JS 继承陷阱,你能全身而退吗?🕳️

继承,是 JS 面试绕不开的灵魂拷问。本文将带你一网打尽 JS 继承的所有姿势,配合代码实例和细致讲解,助你面试不再慌张!

一、什么是继承?

继承,就是让子类可以访问到父类的属性和方法。JS 继承的实现方式多如牛毛,面试官最爱考察各种细节和坑点。

二、原型链继承

原理

子类的原型指向父类的实例。所有子类实例共享同一个父类实例。

代码演示

javascript 复制代码
function Parent() {
    this.name = 'parent'
    this.like = ['a', 'b', 'c']
}
Child.prototype = new Parent()
function Child() {
    this.age = 18
}
let c = new Child()
let d = new Child()
c.like.push('d')
console.log(c.like) // ['a', 'b', 'c', 'd']
console.log(d.like) // ['a', 'b', 'c', 'd']

优缺点

  • 优点:实现简单,能访问父类属性和方法。
  • 缺点:引用类型属性会被所有实例共享,互相影响,容易踩坑。

面试官小贴士

"你能说说原型链继承的缺陷吗?为什么 like 属性会被所有实例共享?"

三、构造函数继承

原理

在子类构造函数中调用父类构造函数,this 指向子类实例。

代码演示

javascript 复制代码
Parent.prototype.say = function () {
    console.log('hello')
}
function Parent() {
    this.name = 'parent'
    this.like = ['a', 'b', 'c']
}
function Child() {
    this.age = 18
    Parent.call(this)
}
let c = new Child()
console.log(c.say) // undefined

优缺点

  • 优点:每个实例独立拥有父类属性,引用类型不再共享。
  • 缺点:无法继承父类原型上的方法(如 say),只能继承构造函数里的属性。

面试官小贴士

"为什么 c.say 是 undefined?如何让子类也能继承父类原型上的方法?"

四、组合继承

原理

原型链继承 + 构造函数继承,双管齐下。

代码演示

javascript 复制代码
Parent.prototype.say = function () {
    console.log('hello')
}
function Parent() {
    this.name = 'parent'
    this.like = ['a', 'b', 'c']
}
Child.prototype = new Parent()
Child.prototype.constructor = Child
function Child() {
    this.age = 18
    Parent.call(this)
}
let c = new Child()
let d = new Child()
d.like.push('d')
console.log(d.like); // ['a', 'b', 'c', 'd']
console.log(c.like); // ['a', 'b', 'c']
console.log(c.say); // function
console.log(c.constructor); // Child

优缺点

  • 优点:既能继承父类属性,又能继承父类原型方法,引用类型不共享。
  • 缺点:父类构造函数会执行两次(一次给原型,一次给实例),有点浪费性能。

面试官小贴士

"组合继承为什么会调用两次父类构造函数?有没有更优的方案?"

五、原型式继承

原理

用 Object.create 或类似方式,以某对象为原型创建新对象。

代码演示

javascript 复制代码
let parent = {
    name: 'parent',
    like: ['a', 'b', 'c']
}
let child1 = Object.create(parent)
let child2 = Object.create(parent)
child1.like.push('d')
console.log(child1.like); // ['a', 'b', 'c', 'd']
console.log(child2.like); // ['a', 'b', 'c', 'd']

优缺点

  • 优点:实现简单,适合对象克隆。
  • 缺点:引用类型属性依然共享。

面试官小贴士

"Object.create(parent) 和 new Object(parent) 有什么区别?"

六、寄生式继承

原理

在原型式继承基础上,增强返回的新对象。

代码演示

javascript 复制代码
let parent = {
    name: 'parent',
    like: ['a', 'b', 'c']
}
function clone(origin) {
    let cloneObj = Object.create(origin)
    cloneObj.getLike = function() {
        return this.like
    }
    return cloneObj
}
let child1 = clone(parent)
let child2 = clone(parent)
child1.like.push('d')
console.log(child1.like); // ['a', 'b', 'c', 'd']
console.log(child2.like); // ['a', 'b', 'c', 'd']
console.log(child1.getLike()); // ['a', 'b', 'c', 'd']
console.log(child2.getLike()); // ['a', 'b', 'c', 'd']

优缺点

  • 优点:可以扩展新对象。
  • 缺点:引用类型属性依然共享。

面试官小贴士

"寄生式继承和原型式继承的本质区别是什么?"

七、寄生组合式继承(最优解)

原理

只继承父类原型,不调用父类构造函数,避免性能浪费。

代码演示

javascript 复制代码
Parent.prototype.getName = function() {
    return this.Name
}
function Parent() {
    this.Name = 'parent'
    this.like = ['a', 'b', 'c']
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
function Child() {
    this.age = 18
    Parent.call(this)
}
let c1 = new Child()
console.log(c1.getName()); // 'parent'
console.log(c1.constructor); // Child

优缺点

  • 优点:只调用一次父类构造函数,性能最佳,继承属性和方法都不落下。
  • 缺点:实现稍复杂,但值得!

面试官小贴士

"为什么寄生组合式继承被称为 JS 继承的终极方案?"

八、ES6 类继承

原理

用 class 和 extends 语法糖,优雅实现继承。

代码演示

javascript 复制代码
class Parent {
    constructor() {
        this.Name = 'parent'
        this.like = ['a', 'b', 'c']
    }
    getName() {
        return this.Name
    }
    static say() {
        console.log('hello');
    }
}
class Child extends Parent {
    constructor() {
        super()
        this.age = 18
    }
}
let p = new Parent()
console.log(p.getName()); // 'parent'
let c = new Child()
console.log(c.getName()); // 'parent'

优缺点

  • 优点:语法简洁,继承关系清晰,原型链自动处理。
  • 缺点:底层依然是原型链,只是语法糖。

面试官小贴士

"class 继承和传统原型链继承的本质区别是什么?"

九、知识点总结与面试答题模板

继承方式对比表

方式 是否共享引用类型 是否继承原型方法 构造函数调用次数 优缺点
原型链继承 1 引用类型共享
构造函数继承 1 不能继承原型方法
组合继承 2 性能浪费
原型式继承 0 引用类型共享
寄生式继承 0 引用类型共享
寄生组合式继承 1 性能最佳
ES6 类继承 1 语法糖

面试高频问题

  • 说说 JS 继承的实现方式及优缺点?
  • 为什么原型链继承会导致引用类型属性共享?
  • 如何实现一个既能继承属性又能继承方法的子类?
  • ES6 的 class 继承和传统继承有什么区别?

十、幽默收尾

JS 继承就像家庭聚会,谁家锅碗瓢盆都能借来用,但有时候大家都用同一个锅,炒出来的菜味道就不一样了!面试官最爱问的那些继承细节,你现在都能用段子和代码轻松拿下!


祝大家面试不再慌张,继承全家桶一把梭!🎉

相关推荐
郭老二16 小时前
【前端】vue3:编译步骤
前端
不在逃避q17 小时前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
夏殇之殁17 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One98517 小时前
高进度算法模板速记(待完善)
java·前端·算法
陈随易18 小时前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
新中地GIS开发老师19 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
用户0595401744619 小时前
大模型对话记忆持久化踩坑实录:用 Playwright 自动化测了 300 次,终于揪出会话丢失的真凶
前端·css
丙氨酸長鏈19 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
kyriewen20 小时前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
IT_陈寒20 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端