Skip to content

ES6高频面试题


1. 什么是ES6?它的主要特性有哪些?

参考答案:

ES6(ECMAScript 2015)是JavaScript的第六个版本,是JavaScript语言的重大更新。主要特性包括:

  • let和const关键字
  • 箭头函数
  • 模板字符串
  • 解构赋值
  • 默认参数
  • 扩展运算符
  • Promise
  • 类(Class)
  • 模块化(import/export)
  • Symbol数据类型
  • Map和Set数据结构
  • 生成器函数(Generator)

2. let、const和var的区别是什么?

参考答案:

  • 作用域:var是函数作用域,let和const是块级作用域
  • 变量提升:var存在变量提升,let和const存在暂时性死区
  • 重复声明:var允许重复声明,let和const不允许
  • 赋值:var和let可以重新赋值,const不能重新赋值(但对象内容可修改)
  • 初始化:var和let可以不初始化,const必须初始化

3. 什么是箭头函数?它与普通函数有什么区别?

参考答案:

箭头函数是ES6新增的函数定义方式,语法更简洁。主要区别:

  • this指向:箭头函数没有自己的this,继承外层作用域的this
  • arguments对象:箭头函数没有arguments对象
  • 构造函数:箭头函数不能作为构造函数使用
  • 原型:箭头函数没有prototype属性
  • 变量提升:箭头函数不存在变量提升
  • 箭头函数最大作用就是消除函数的二义性

4. 什么是模板字符串?它有什么优势?

参考答案:

模板字符串使用反引号()包围,可以包含占位符(${expression}`)。优势:

  • 支持多行字符串
  • 支持变量插值
  • 支持表达式计算
  • 更直观的字符串拼接
  • 支持标签模板功能

5. 解构赋值是什么?请举例说明数组和对象的解构。

参考答案:

解构赋值是一种从数组或对象中提取值并赋给变量的语法。

javascript
// 数组解构
const [a, b, c] = [1, 2, 3]
const [x, , z] = [1, 2, 3] // 跳过中间元素

// 对象解构
const { name, age } = { name: 'John', age: 30 }
const { name: userName, age: userAge } = obj // 重命名

6. 什么是扩展运算符(...)?它有哪些用途?

参考答案:

扩展运算符(...)可以将可迭代对象展开。用途包括:

  • 数组展开:[...arr1, ...arr2]
  • 对象展开:{...obj1, ...obj2}
  • 函数参数展开:func(...args)
  • 复制数组/对象:[...arr]{...obj}
  • 将类数组对象转为数组:[...nodeList]

7. 什么是剩余参数(rest parameters)?

参考答案:

剩余参数使用...语法,将多个参数收集到一个数组中:

javascript
function sum(...numbers) {
  return numbers.reduce((a, b) => a + b, 0)
}
sum(1, 2, 3, 4) // numbers = [1, 2, 3, 4]

剩余参数必须是最后一个参数,一个函数只能有一个剩余参数。


8. ES6中的默认参数是如何工作的?

参考答案:

ES6允许为函数参数设置默认值:

javascript
function greet(name = 'World') {
  return `Hello, ${name}!`
}
  • 只有当参数为undefined时才使用默认值
  • 默认参数可以是表达式或函数调用
  • 默认参数可以引用前面的参数
  • 有默认值的参数应该放在后面

9. 什么是Promise?它解决了什么问题?

参考答案:

Promise是处理异步操作的对象,有三种状态:pending、fulfilled、rejected。

解决的问题:

  • 回调地狱问题
  • 错误处理困难
  • 异步操作的组合和串联
  • 提供了更好的异步编程模式

基本用法:

javascript
const promise = new Promise((resolve, reject) => {
  // 异步操作
})
promise.then(result => {}).catch(error => {})

10. ES6的类(Class)是如何工作的?

参考答案:

ES6的类是基于原型的语法糖:

javascript
class Person {
  constructor(name) {
    this.name = name
  }

  sayHello() {
    return `Hello, I'm ${this.name}`
  }

  static getSpecies() {
    return 'Homo sapiens'
  }
}
  • constructor定义构造函数
  • 方法定义在原型上
  • 支持静态方法
  • 支持继承(extends)

11. ES6模块化(import/export)是如何工作的?

参考答案:

ES6提供了原生的模块化支持:

javascript
// 导出
export const name = 'John'
export function greet() {}
export default class Person {}

// 导入
import Person, { name, greet } from './module.js'
import * as utils from './utils.js'
  • 静态导入导出
  • 编译时确定依赖关系
  • 支持默认导出和命名导出
  • 自动严格模式

12. Symbol数据类型有什么特点和用途?

参考答案:

Symbol是ES6新增的原始数据类型,表示独一无二的值。特点:

  • 每个Symbol值都是唯一的
  • 不能与其他值进行运算
  • 可以作为对象属性名
  • 不会被常规方法遍历到

用途:

  • 创建对象的私有属性
  • 定义对象的元数据
  • 避免属性名冲突
  • 实现迭代器接口

13. Map和Set数据结构有什么特点?

参考答案:

Map特点:

  • 键值对集合,键可以是任意类型
  • 有序,按插入顺序遍历
  • size属性获取大小
  • 方法:set、get、has、delete、clear

Set特点:

  • 值的集合,值唯一
  • 有序,按插入顺序遍历
  • size属性获取大小
  • 方法:add、has、delete、clear
  • 可用于数组去重

14. 什么是生成器函数(Generator)?

参考答案:

生成器函数是可以暂停和恢复执行的函数,使用function*定义:

javascript
function* generator() {
  yield 1
  yield 2
  return 3
}

const gen = generator()
gen.next() // {value: 1, done: false}
gen.next() // {value: 2, done: false}
gen.next() // {value: 3, done: true}

特点:

  • 返回迭代器对象
  • 可以暂停和恢复执行
  • 用于实现异步编程
  • 可以双向通信

15. 什么是迭代器(Iterator)和可迭代对象?

参考答案:

迭代器:实现了next()方法的对象,返回{value, done}格式的结果。

可迭代对象:实现了Symbol.iterator方法的对象。

内置可迭代对象:Array、String、Map、Set、arguments等。

javascript
const arr = [1, 2, 3]
const iterator = arr[Symbol.iterator]()
iterator.next() // {value: 1, done: false}

16. for...of和for...in的区别是什么?

参考答案:

  • for...in:遍历对象的可枚举属性名(包括继承的)
  • for...of:遍历可迭代对象的值
javascript
const arr = [1, 2, 3]
arr.name = 'array'

for (let key in arr) {
  console.log(key) // 0, 1, 2, name
}

for (let value of arr) {
  console.log(value) // 1, 2, 3
}

17. 什么是Proxy?它有什么用途?

参考答案:

Proxy用于定义基本操作的自定义行为(如属性查找、赋值等):

javascript
const proxy = new Proxy(target, handler)

用途:

  • 属性访问拦截
  • 函数调用拦截
  • 数据验证
  • 属性默认值
  • 实现观察者模式
  • Vue3的响应式原理

常用handler方法:get、set、has、deleteProperty等。


18. 什么是Reflect?它与Proxy有什么关系?

参考答案:

Reflect是一个内置对象,提供了拦截JavaScript操作的方法。

特点:

  • 方法与Proxy handler方法一一对应
  • 提供了默认的对象操作行为
  • 返回值更合理(布尔值而不是抛出异常)
javascript
// 传统方式
delete obj.prop

// Reflect方式
Reflect.deleteProperty(obj, 'prop') // 返回boolean

与Proxy配合使用可以实现更好的元编程。


19. 什么是WeakMap和WeakSet?它们与Map、Set有什么区别?

参考答案:

WeakMap和WeakSet的特点:

  • 键/值必须是对象
  • 弱引用,不阻止垃圾回收
  • 不可遍历,没有size属性
  • 没有clear方法

与Map、Set的区别:

  • 引用类型:弱引用 vs 强引用
  • 垃圾回收:不阻止 vs 阻止
  • 遍历性:不可遍历 vs 可遍历
  • 用途:存储私有数据 vs 一般数据存储

20. 什么是暂时性死区(Temporal Dead Zone)?

参考答案:

暂时性死区是指let和const声明的变量在声明之前不能被访问的区域。

javascript
console.log(a) // ReferenceError
let a = 1

function func() {
  console.log(b) // ReferenceError
  let b = 2
}

特点:

  • 从块级作用域开始到变量声明之前
  • 访问会抛出ReferenceError
  • typeof操作符也会报错
  • 确保变量先声明后使用

21. ES6中的对象字面量有哪些增强?

参考答案:

ES6对象字面量增强包括:

  1. 属性简写:{name, age} 等价于 {name: name, age: age}
  2. 方法简写:{method() {}} 等价于 {method: function() {}}
  3. 计算属性名:{[key]: value}
  4. 可以使用表达式作为属性名
  5. super关键字:在方法中调用原型方法
javascript
const name = 'John'
const obj = {
  name, // 属性简写
  greet() {}, // 方法简写
  [name + 'Key']: 'value' // 计算属性名
}

22. 什么是数组的新方法?请列举几个ES6新增的数组方法。

参考答案:

ES6为数组新增了多个方法:

  • Array.from():将类数组对象转为数组
  • Array.of():创建数组,避免Array构造函数的怪异行为
  • find():找到第一个满足条件的元素
  • findIndex():找到第一个满足条件的元素索引
  • includes():判断数组是否包含某个值
  • fill():用指定值填充数组
  • keys()values()entries():返回迭代器

23. 什么是字符串的新方法?ES6为字符串添加了哪些方法?

参考答案:

ES6为字符串新增的方法:

  • includes():判断是否包含子字符串
  • startsWith():判断是否以指定字符串开头
  • endsWith():判断是否以指定字符串结尾
  • repeat():重复字符串指定次数
  • padStart():在开头填充字符串到指定长度
  • padEnd():在末尾填充字符串到指定长度
javascript
'hello'.includes('ell') // true
'hello'.startsWith('he') // true
'hello'.repeat(2) // 'hellohello'

24. 什么是参数解构?请举例说明。

参考答案:

参数解构是在函数参数中直接解构传入的对象或数组:

javascript
// 对象参数解构
function greet({ name, age = 18 }) {
  console.log(`Hello ${name}, age ${age}`)
}
greet({ name: 'John', age: 25 })

// 数组参数解构
function sum([a, b]) {
  return a + b
}
sum([1, 2])

// 嵌套解构
function process({ user: { name, email } }) {
  console.log(name, email)
}

25. 什么是尾调用优化?ES6如何支持尾调用优化?

参考答案:

尾调用是指函数的最后一步调用另一个函数。尾调用优化是指在尾调用时不增加新的栈帧,而是复用当前栈帧。

ES6在严格模式下支持尾调用优化:

javascript
'use strict'
function factorial(n, acc = 1) {
  if (n <= 1) return acc
  return factorial(n - 1, n * acc) // 尾调用
}

条件:

  • 严格模式
  • 尾调用不访问当前栈帧的变量
  • 尾调用是函数的最后一个操作

26. 什么是标签模板?它有什么用途?

参考答案:

标签模板是模板字符串的高级形式,允许用函数解析模板字符串:

javascript
function highlight(strings, ...values) {
  return strings.reduce((result, string, i) => {
    return result + string + (values[i] ? `<mark>${values[i]}</mark>` : '')
  }, '')
}

const name = 'John'
const age = 25
const result = highlight`Hello ${name}, you are ${age} years old`

用途:

  • 字符串处理和转换
  • 模板引擎
  • 国际化
  • 防止XSS攻击

27. ES6中的正则表达式有哪些新特性?

参考答案:

ES6为正则表达式添加了新特性:

  1. u标志:Unicode模式,正确处理大于\uFFFF的Unicode字符
  2. y标志:粘连模式,从lastIndex位置开始匹配
  3. RegExp构造函数增强:可以接受正则表达式作为参数
  4. 新方法:flags属性获取修饰符
javascript
const regex = /\u{1D306}/u // Unicode模式
const sticky = /hello/y // 粘连模式
regex.flags // 'u'

28. 什么是二进制和八进制字面量?

参考答案:

ES6提供了二进制和八进制数值的新写法:

javascript
// 二进制(0b或0B开头)
const binary = 0b1010 // 10
const binary2 = 0b1010 // 10

// 八进制(0o或0O开头)
const octal = 0o755 // 493
const octal2 = 0o755 // 493

// 检测方法
Number.isFinite(binary) // true
Number.isInteger(octal) // true

注意:严格模式下不支持0开头的八进制写法。


29. ES6中的Number对象有哪些新方法?

参考答案:

ES6为Number对象新增了多个方法:

  • Number.isFinite():检测数值是否有限
  • Number.isNaN():检测是否为NaN
  • Number.parseInt():解析整数
  • Number.parseFloat():解析浮点数
  • Number.isInteger():判断是否为整数
  • Number.isSafeInteger():判断是否在安全整数范围内
  • Number.EPSILON:最小精度常量
  • Number.MAX_SAFE_INTEGER/MIN_SAFE_INTEGER:安全整数范围

30. 什么是Object.assign()?它有什么特点和用途?

参考答案:

Object.assign()用于将源对象的可枚举属性复制到目标对象:

javascript
const target = { a: 1 }
const source = { b: 2, c: 3 }
Object.assign(target, source) // {a: 1, b: 2, c: 3}

特点:

  • 浅拷贝,不会拷贝继承属性和不可枚举属性
  • 同名属性会被覆盖
  • 返回目标对象
  • 可以接受多个源对象

用途:

  • 对象合并
  • 对象克隆
  • 为对象添加属性
  • 为对象添加方法

基于 VitePress 的本地知识库