Skip to content

ES6 经典面试题

1. 什么是 ES6?

ES6(ECMAScript 2015)是 JavaScript 语言的标准,于 2015 年发布。它引入了许多新特性,如箭头函数、类、模板字符串、解构赋值等,旨在使 JavaScript 更加强大和易于使用。

答案: ES6 是 ECMAScript 2015 的简称,是 JavaScript 语言的一次重大更新,引入了众多新特性,包括但不限于:箭头函数、类、模板字符串、解构赋值、默认参数、剩余参数、扩展运算符、let 和 const 声明、Promise、模块化等。这些特性大大提升了 JavaScript 的开发效率和代码可读性。

2. let、const 和 var 的区别

答案:

  • var: 函数作用域,存在变量提升,可以重复声明,值可以被修改。
  • let: 块级作用域,不存在变量提升,不能重复声明,值可以被修改。
  • const: 块级作用域,不存在变量提升,不能重复声明,值不能被修改(但如果是对象或数组,其内部属性或元素可以被修改)。

优缺点分析:

  • var: 优点是兼容性好,缺点是作用域混乱,容易导致变量污染。
  • let: 优点是作用域清晰,避免变量污染,缺点是在某些旧浏览器中可能不支持。
  • const: 优点是值不可变,提高代码可靠性,缺点是使用不当可能导致困惑(如对象内部可修改)。

3. 箭头函数的特点以及为什么要引入箭头函数?

答案: 箭头函数是 ES6 中引入的一种新的函数声明方式作用是消除函数的二义性,具有以下特点:

  1. 语法简洁,使用 => 符号定义
  2. 没有自己的 this,会继承父级作用域的 this
  3. 不能作为构造函数使用
  4. 没有 arguments 对象
  5. 不能使用 yield 关键字(不能作为生成器函数)

优缺点分析:

  • 优点: 语法简洁,解决了 this 指向问题,减少了代码冗余。
  • 缺点: 不能作为构造函数,没有 arguments 对象,在某些场景下可能不如普通函数灵活。

4. 模板字符串的用法

答案: 模板字符串使用反引号()包裹,可以在其中插入变量或表达式,使用 ${}` 语法:

javascript
const name = 'John'
const age = 30
const message = `My name is ${name}, and I'm ${age} years old.`

优缺点分析:

  • 优点: 语法简洁,支持多行字符串,避免了字符串拼接的繁琐。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 Babel 等工具转译。

5. 解构赋值的应用

答案: 解构赋值允许我们从数组或对象中提取值,并将其赋给变量:

javascript
// 数组解构
const [a, b, c] = [1, 2, 3]

// 对象解构
const { name, age } = { name: 'John', age: 30 }

// 嵌套解构
const {
  user: { name }
} = { user: { name: 'John', age: 30 } }

优缺点分析:

  • 优点: 语法简洁,减少了代码冗余,提高了代码可读性。
  • 缺点: 解构赋值的语法可能对初学者来说有些复杂。

6. 默认参数的使用

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

javascript
function greet(name = 'World') {
  return `Hello, ${name}!`
}

greet() // 输出: Hello, World!
greet('John') // 输出: Hello, John!

优缺点分析:

  • 优点: 简化了函数参数的处理,避免了手动检查参数是否存在的代码。
  • 缺点: 默认参数的计算是在函数调用时进行的,可能会影响性能(如果默认值是复杂表达式)。

7. 剩余参数和扩展运算符

答案:

  • 剩余参数: 使用 ... 收集剩余的参数到一个数组中:

    javascript
    function sum(...numbers) {
      return numbers.reduce((total, num) => total + num, 0)
    }
  • 扩展运算符: 使用 ... 将数组或对象展开:

    javascript
    const arr1 = [1, 2, 3]
    const arr2 = [...arr1, 4, 5] // [1, 2, 3, 4, 5]
    
    const obj1 = { a: 1 }
    const obj2 = { ...obj1, b: 2 } // { a: 1, b: 2 }

优缺点分析:

  • 优点: 简化了参数处理和数组/对象操作,提高了代码可读性。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 Babel 等工具转译。

8. 类的定义和使用

答案: ES6 引入了类的概念,使用 class 关键字定义:

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

  greet() {
    return `Hello, my name is ${this.name}.`
  }
}

const person = new Person('John', 30)
console.log(person.greet()) // 输出: Hello, my name is John.

优缺点分析:

  • 优点: 语法更清晰,更接近传统面向对象语言,提高了代码可读性。
  • 缺点: 本质上仍然是原型继承的语法糖,可能会让开发者误以为 JavaScript 是真正的面向对象语言。

9. 继承的实现

答案: 使用 extends 关键字实现继承:

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

  greet() {
    return `Hello, my name is ${this.name}.`
  }
}

class Student extends Person {
  constructor(name, age, grade) {
    super(name, age)
    this.grade = grade
  }

  study() {
    return `${this.name} is studying.`
  }
}

const student = new Student('John', 15, 9)
console.log(student.greet()) // 输出: Hello, my name is John.
console.log(student.study()) // 输出: John is studying.

优缺点分析:

  • 优点: 语法简洁,清晰地表达了继承关系。
  • 缺点: 与其他面向对象语言的继承相比,JavaScript 的继承机制仍然有其特殊性(基于原型)。

10. 静态方法和属性

答案: 使用 static 关键字定义静态方法和属性:

javascript
class MathUtils {
  static PI = 3.14159

  static add(a, b) {
    return a + b
  }
}

console.log(MathUtils.PI) // 输出: 3.14159
console.log(MathUtils.add(1, 2)) // 输出: 3

优缺点分析:

  • 优点: 静态方法和属性可以直接通过类名访问,不需要实例化,适合工具类和常量定义。
  • 缺点: 静态成员不能被实例继承,可能会导致代码组织不够灵活。

11. Promise 的基本用法

答案: Promise 是 ES6 中引入的异步编程解决方案,用于处理异步操作:

javascript
const promise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    resolve('Success!')
    // 或 reject('Error!');
  }, 1000)
})

promise
  .then(result => console.log(result))
  .catch(error => console.log(error))
  .finally(() => console.log('Done!'))

优缺点分析:

  • 优点: 解决了回调地狱问题,使异步代码更加清晰易读。
  • 缺点: 错误处理可能不够直观,需要正确使用 catch 方法。

12. async/await 的使用

答案: async/await 是基于 Promise 的语法糖,使异步代码看起来更像同步代码:

javascript
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data')
    const data = await response.json()
    return data
  } catch (error) {
    console.error(error)
  }
}

fetchData().then(data => console.log(data))

优缺点分析:

  • 优点: 语法简洁,使异步代码更加易读和维护。
  • 缺点: 错误处理需要使用 try/catch,在某些情况下可能不如 Promise 的链式调用灵活。

13. 模块化的实现

答案: ES6 引入了模块化系统,使用 importexport 关键字:

javascript
// module.js
export const name = 'John'
export function greet() {
  return `Hello, ${name}!`
}

// main.js
import { name, greet } from './module.js'
console.log(name) // 输出: John
console.log(greet()) // 输出: Hello, John!

优缺点分析:

  • 优点: 代码组织更加清晰,避免了全局变量污染,提高了代码复用性。
  • 缺点: 在浏览器中需要使用打包工具(如 Webpack)或通过 <script type="module"> 标签支持。

14. Set 和 Map 的区别

答案:

  • Set: 存储唯一值的集合,不允许重复元素。

    javascript
    const set = new Set([1, 2, 3, 3])
    console.log(set.size) // 输出: 3
  • Map: 存储键值对的集合,键可以是任意类型。

    javascript
    const map = new Map()
    map.set('name', 'John')
    map.set(1, 'One')
    console.log(map.get('name')) // 输出: John

优缺点分析:

  • Set: 优点是自动去重,缺点是只能存储值,不能存储键值对。
  • Map: 优点是可以使用任意类型作为键,缺点是比对象操作稍复杂。

15. WeakSet 和 WeakMap 的特点

答案:

  • WeakSet: 存储弱引用的对象集合,对象没有其他引用时会被垃圾回收。
  • WeakMap: 存储弱引用的键值对,键必须是对象,没有其他引用时会被垃圾回收。

优缺点分析:

  • 优点: 有助于防止内存泄漏,因为弱引用不会阻止垃圾回收。
  • 缺点: 不能遍历,不能获取大小,只能存储对象(WeakSet)或使用对象作为键(WeakMap)。

16. 迭代器和生成器

答案:

  • 迭代器: 实现了 next() 方法的对象,每次调用返回 { value, done } 对象。
  • 生成器: 使用 function* 定义的函数,返回一个迭代器,可以使用 yield 关键字暂停执行。
javascript
function* generator() {
  yield 1
  yield 2
  yield 3
}

const gen = generator()
console.log(gen.next().value) // 输出: 1
console.log(gen.next().value) // 输出: 2
console.log(gen.next().value) // 输出: 3

优缺点分析:

  • 优点: 提供了一种优雅的方式来处理迭代和异步操作。
  • 缺点: 语法相对复杂,可能对初学者来说难以理解。

17. for...of 循环的使用

答案:for...of 循环用于遍历可迭代对象(如数组、Set、Map 等):

javascript
const arr = [1, 2, 3]
for (const item of arr) {
  console.log(item)
}
// 输出: 1, 2, 3

优缺点分析:

  • 优点: 语法简洁,直接获取值,而不是索引。
  • 缺点: 不能直接获取索引(需要使用 Array.prototype.entries())。

18. 数组的新方法

答案: ES6 为数组添加了许多新方法,如:

  • Array.from():将类数组对象或可迭代对象转换为数组
  • Array.of():创建一个包含任意数量参数的数组
  • find():查找第一个满足条件的元素
  • findIndex():查找第一个满足条件的元素的索引
  • includes():判断数组是否包含某个元素

优缺点分析:

  • 优点: 提供了更多便捷的数组操作方法,提高了代码可读性和开发效率。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 polyfill。

19. 对象的新特性

答案: ES6 为对象添加了许多新特性,如:

  • 简洁属性:const name = 'John'; const obj = { name };
  • 简洁方法:const obj = { greet() { return 'Hello!'; } };
  • 计算属性名:const key = 'name'; const obj = { [key]: 'John' };
  • Object.assign():合并对象
  • Object.getOwnPropertySymbols():获取对象的 Symbol 属性

优缺点分析:

  • 优点: 语法更加简洁,提供了更多对象操作方法。
  • 缺点: 某些特性在旧浏览器中可能不支持。

20. Symbol 的使用

答案: Symbol 是 ES6 中引入的一种新的原始数据类型,用于创建唯一标识符:

javascript
const sym1 = Symbol('description')
const sym2 = Symbol('description')
console.log(sym1 === sym2) // 输出: false

// 作为对象属性
const obj = {
  [sym1]: 'value'
}

优缺点分析:

  • 优点: 可以创建唯一的对象属性名,避免属性名冲突。
  • 缺点: 不能被 JSON.stringify() 序列化,可能会导致一些意外行为。

21. 代理(Proxy)的使用

答案: Proxy 用于创建一个对象的代理,拦截并自定义对象的操作:

javascript
const target = { name: 'John' }
const proxy = new Proxy(target, {
  get(target, prop) {
    return prop in target ? target[prop] : 'Not found'
  },
  set(target, prop, value) {
    console.log(`Setting ${prop} to ${value}`)
    target[prop] = value
    return true
  }
})

console.log(proxy.name) // 输出: John
console.log(proxy.age) // 输出: Not found
proxy.age = 30 // 输出: Setting age to 30

优缺点分析:

  • 优点: 提供了一种强大的方式来拦截和自定义对象操作,可用于实现数据验证、日志记录等功能。
  • 缺点: 性能可能比直接操作对象稍差,在某些场景下可能会导致代码复杂度增加。

22. 反射(Reflect)的使用

答案: Reflect 是 ES6 中引入的一个内置对象,提供了与对象操作相关的方法:

javascript
const obj = { name: 'John' }
console.log(Reflect.has(obj, 'name')) // 输出: true
console.log(Reflect.get(obj, 'name')) // 输出: John
Reflect.set(obj, 'age', 30)
console.log(obj.age) // 输出: 30

优缺点分析:

  • 优点: 提供了一种统一的方式来操作对象,与 Proxy 配合使用效果更佳。
  • 缺点: 浏览器支持情况可能不一致,需要使用 polyfill。

23. 数值的新特性

答案: ES6 为数值添加了许多新特性,如:

  • 二进制和八进制字面量:0b1010(二进制)、0o777(八进制)
  • Number.isFinite():判断一个数是否是有限的
  • Number.isNaN():判断一个值是否是 NaN
  • Number.isInteger():判断一个数是否是整数
  • Math.trunc():去除小数部分
  • Math.sign():返回数字的符号

优缺点分析:

  • 优点: 提供了更多数值操作方法,使数值处理更加方便。
  • 缺点: 在某些旧浏览器中可能不支持。

24. 字符串的新方法

答案: ES6 为字符串添加了许多新方法,如:

  • startsWith():判断字符串是否以指定字符开始
  • endsWith():判断字符串是否以指定字符结束
  • includes():判断字符串是否包含指定字符
  • repeat():重复字符串指定次数

优缺点分析:

  • 优点: 提供了更多字符串操作方法,使字符串处理更加方便。
  • 缺点: 在某些旧浏览器中可能不支持。

25. 正则表达式的新特性

答案: ES6 为正则表达式添加了一些新特性,如:

  • 修饰符 u(Unicode 模式):正确处理 Unicode 字符
  • 修饰符 y(粘性模式):从目标字符串的当前位置开始匹配
  • RegExp.prototype.flags:获取正则表达式的修饰符

优缺点分析:

  • 优点: 提供了更多正则表达式功能,特别是对 Unicode 的支持。
  • 缺点: 在某些旧浏览器中可能不支持。

26. 解构赋值的高级用法

答案: 解构赋值的高级用法包括:

  • 嵌套解构:const { user: { name } } = { user: { name: 'John' } }
  • 剩余模式:const [first, ...rest] = [1, 2, 3, 4]
  • 解构并重命名:const { name: username } = { name: 'John' }
  • 解构默认值:const { name = 'World' } = {}

优缺点分析:

  • 优点: 语法简洁,功能强大,提高了代码可读性。
  • 缺点: 语法可能对初学者来说有些复杂。

27. 扩展运算符的高级用法

答案: 扩展运算符的高级用法包括:

  • 数组复制:const arr2 = [...arr1]
  • 数组合并:const arr3 = [...arr1, ...arr2]
  • 对象复制:const obj2 = { ...obj1 }
  • 对象合并:const obj3 = { ...obj1, ...obj2 }
  • 函数参数:function sum(...numbers) { return numbers.reduce((a, b) => a + b); }

优缺点分析:

  • 优点: 语法简洁,功能强大,提高了代码可读性。
  • 缺点: 在某些旧浏览器中可能不支持。

28. Promise 的高级用法

答案: Promise 的高级用法包括:

  • Promise.all():等待所有 Promise 完成
  • Promise.race():等待第一个完成的 Promise
  • Promise.allSettled():等待所有 Promise 完成(无论成功或失败)
  • Promise.any():等待第一个成功的 Promise

优缺点分析:

  • 优点: 提供了处理多个异步操作的便捷方法。
  • 缺点: 错误处理可能不够直观,需要仔细处理。

29. async/await 的高级用法

答案: async/await 的高级用法包括:

  • 并行执行:使用 Promise.all() 配合 async/await
  • 错误处理:使用 try/catch 捕获错误
  • 顺序执行:使用 for 循环配合 async/await

优缺点分析:

  • 优点: 语法简洁,使异步代码更加易读。
  • 缺点: 在某些情况下可能会导致代码执行效率降低(如未正确使用并行执行)。

30. 模块化的高级用法

答案: 模块化的高级用法包括:

  • 默认导出:export default function() {}
  • 命名导出:export const name = 'John'
  • 重新导出:export { name } from './module.js'
  • 动态导入:import('./module.js').then(module => {})

优缺点分析:

  • 优点: 提供了灵活的模块导出和导入方式。
  • 缺点: 动态导入在某些旧浏览器中可能不支持。

31. 类的高级特性

答案: 类的高级特性包括:

  • getter 和 setter:get name() { return this._name; } set name(value) { this._name = value; }
  • 私有字段:使用 # 前缀,如 #privateField
  • 静态字段:static staticField = 'value'
  • 类表达式:const Person = class { constructor(name) { this.name = name; } }

优缺点分析:

  • 优点: 提供了更多面向对象编程的特性,使代码更加清晰。
  • 缺点: 私有字段等特性在某些旧浏览器中可能不支持。

32. 箭头函数与普通函数的区别

答案: 箭头函数与普通函数的主要区别:

  1. 语法不同:箭头函数使用 => 符号
  2. this 指向不同:箭头函数继承父级作用域的 this,普通函数的 this 取决于调用方式
  3. 构造函数:箭头函数不能作为构造函数,普通函数可以
  4. arguments 对象:箭头函数没有 arguments 对象,普通函数有
  5. yield 关键字:箭头函数不能使用 yield,普通函数可以

优缺点分析:

  • 箭头函数: 优点是语法简洁,解决了 this 指向问题;缺点是功能相对受限。
  • 普通函数: 优点是功能完整,使用灵活;缺点是 this 指向可能会导致困惑。

33. let 和 const 的暂时性死区

答案: 暂时性死区(Temporal Dead Zone,TDZ)是指在使用 let 或 const 声明变量之前,该变量不可用的区域:

javascript
console.log(a) // ReferenceError: a is not defined
let a = 1

优缺点分析:

  • 优点: 避免了变量提升可能导致的问题,使代码更加可预测。
  • 缺点: 可能会导致一些意外的 ReferenceError。

34. 解构赋值的性能影响

答案: 解构赋值在某些情况下可能会对性能产生影响,特别是在处理大型对象或数组时。但在大多数情况下,这种影响是可以忽略不计的,因为现代 JavaScript 引擎会对解构赋值进行优化。

优缺点分析:

  • 优点: 提高了代码可读性和开发效率。
  • 缺点: 在处理大型数据结构时可能会有轻微的性能开销。

35. Promise 的错误处理

答案: Promise 的错误处理可以通过 .catch() 方法或 try/catch(配合 async/await)来实现:

javascript
// 使用 .catch()
promise.then(result => console.log(result)).catch(error => console.error(error))

// 使用 try/catch(配合 async/await)
async function fetchData() {
  try {
    const result = await promise
    console.log(result)
  } catch (error) {
    console.error(error)
  }
}

优缺点分析:

  • 优点: 提供了统一的错误处理机制,避免了回调地狱中的错误处理混乱。
  • 缺点: 在某些情况下,错误可能会被忽略(如忘记添加 .catch())。

36. async/await 与 Promise 的关系

答案: async/await 是基于 Promise 的语法糖,async 函数返回一个 Promise,await 操作符用于等待 Promise 解决。

优缺点分析:

  • 优点: 使异步代码更加易读,看起来像同步代码。
  • 缺点: 本质上仍然是 Promise,需要了解 Promise 的工作原理。

37. 模块化与 CommonJS 的区别

答案: ES6 模块化与 CommonJS 的主要区别:

  1. 语法不同:ES6 使用 import/export,CommonJS 使用 require/module.exports
  2. 加载方式不同:ES6 是静态加载(编译时),CommonJS 是动态加载(运行时)
  3. 适用环境不同:ES6 模块化适用于浏览器和 Node.js,CommonJS 主要适用于 Node.js

优缺点分析:

  • ES6 模块化: 优点是静态加载,有利于树摇和类型检查;缺点是在某些环境中需要转译。
  • CommonJS: 优点是动态加载,灵活性高;缺点是不利于树摇。

38. Set 和 Array 的区别

答案: Set 和 Array 的主要区别:

  1. Set 存储唯一值,Array 可以存储重复值
  2. Set 没有索引,Array 有索引
  3. Set 的查找速度比 Array 快(时间复杂度 O(1) vs O(n))
  4. Set 没有 pushpop 等方法,需要使用 adddelete 等方法

优缺点分析:

  • Set: 优点是自动去重,查找速度快;缺点是没有索引,操作不如 Array 灵活。
  • Array: 优点是操作灵活,有丰富的方法;缺点是需要手动去重,查找速度较慢。

39. Map 和 Object 的区别

答案: Map 和 Object 的主要区别:

  1. Map 的键可以是任意类型,Object 的键只能是字符串或 Symbol
  2. Map 的大小可以通过 size 属性获取,Object 的大小需要手动计算
  3. Map 是可迭代的,Object 需要通过 Object.keys() 等方法才能迭代
  4. Map 的插入和删除操作性能更好

优缺点分析:

  • Map: 优点是键类型灵活,大小可直接获取,迭代方便;缺点是操作稍复杂。
  • Object: 优点是语法简洁,使用方便;缺点是键类型受限,大小需要手动计算。

40. 箭头函数中的 this 指向

答案: 箭头函数没有自己的 this,它会继承父级作用域的 this。这意味着箭头函数中的 this 指向在定义时就已经确定,不会受到调用方式的影响。

优缺点分析:

  • 优点: 解决了传统函数中 this 指向不确定的问题,使代码更加可预测。
  • 缺点: 在某些需要动态 this 的场景下可能不适用。

41. 类的继承与原型继承的关系

答案: ES6 类的继承本质上是原型继承的语法糖。当使用 class A extends B 时,A 的原型会指向 B 的实例,从而实现继承。

优缺点分析:

  • 优点: 语法更加清晰,更接近传统面向对象语言。
  • 缺点: 可能会让开发者误以为 JavaScript 是真正的面向对象语言,而忽略其原型继承的本质。

42. Promise 的状态变化

答案: Promise 有三种状态:

  1. pending(进行中):初始状态,既不是成功也不是失败
  2. fulfilled(已成功):操作成功完成
  3. rejected(已失败):操作失败

Promise 的状态一旦改变,就不会再变。

优缺点分析:

  • 优点: 状态管理清晰,避免了回调地狱。
  • 缺点: 一旦创建就无法取消,可能会导致内存泄漏(如果 Promise 永远不 resolve 或 reject)。

43. async/await 的错误处理最佳实践

答案: async/await 的错误处理最佳实践:

  1. 使用 try/catch 捕获错误
  2. 对于可能失败的操作,始终使用 try/catch 包裹
  3. 可以在 catch 块中进行错误处理或向上抛出
  4. 对于多个异步操作,可以使用 Promise.all() 配合 try/catch

优缺点分析:

  • 优点: 错误处理更加直观,代码更加清晰。
  • 缺点: 如果忘记添加 try/catch,错误可能会被静默忽略。

44. 模块化的树摇(Tree Shaking)

答案: 树摇是指在打包过程中,移除未使用的代码。ES6 模块化的静态加载特性使得树摇成为可能,因为打包工具可以在编译时确定哪些代码被使用,哪些代码未被使用。

优缺点分析:

  • 优点: 减少打包体积,提高应用性能。
  • 缺点: 依赖于打包工具的实现,可能需要特定的配置。

45. Set 的应用场景

答案: Set 的应用场景包括:

  1. 数组去重:const uniqueArray = [...new Set(array)]
  2. 存储唯一值:如用户 ID、标签等
  3. 检查值是否存在:set.has(value)
  4. 遍历操作:使用 for...of 循环

优缺点分析:

  • 优点: 自动去重,查找速度快,操作简洁。
  • 缺点: 没有索引,不能直接访问元素。

46. Map 的应用场景

答案: Map 的应用场景包括:

  1. 存储键值对,其中键不是字符串:如对象作为键
  2. 需要频繁添加和删除键值对的场景
  3. 需要获取键值对数量的场景:map.size
  4. 需要保持插入顺序的场景:Map 会保持键值对的插入顺序

优缺点分析:

  • 优点: 键类型灵活,操作高效,保持插入顺序。
  • 缺点: 语法稍复杂,在某些旧浏览器中不支持。

47. WeakSet 和 WeakMap 的应用场景

答案: WeakSet 和 WeakMap 的应用场景包括:

  1. 存储临时对象:当对象没有其他引用时会被垃圾回收
  2. 避免内存泄漏:如缓存、事件监听器等
  3. 存储与对象相关的元数据:不影响对象的垃圾回收

优缺点分析:

  • 优点: 有助于防止内存泄漏,适合存储临时数据。
  • 缺点: 不能遍历,不能获取大小,功能相对受限。

48. 生成器的应用场景

答案: 生成器的应用场景包括:

  1. 惰性计算:按需生成值,节省内存
  2. 异步操作:使用 co 库或 async/await
  3. 迭代器实现:自定义可迭代对象
  4. 状态管理:保存函数执行状态

优缺点分析:

  • 优点: 提供了一种优雅的方式来处理迭代和异步操作。
  • 缺点: 语法相对复杂,可能对初学者来说难以理解。

49. 代理(Proxy)的应用场景

答案: 代理的应用场景包括:

  1. 数据验证:拦截并验证属性赋值
  2. 日志记录:记录对象的操作
  3. 数据绑定:实现响应式数据
  4. 私有属性:模拟私有属性
  5. 缓存:缓存对象的操作结果

优缺点分析:

  • 优点: 提供了强大的对象操作拦截能力,可用于实现各种高级功能。
  • 缺点: 性能可能比直接操作对象稍差,在某些场景下可能会导致代码复杂度增加。

50. 反射(Reflect)的应用场景

答案: 反射的应用场景包括:

  1. 与 Proxy 配合使用:提供统一的对象操作方法
  2. 动态操作对象:如动态获取、设置属性
  3. 检查对象属性:如 Reflect.has()Reflect.ownKeys()
  4. 调用函数:Reflect.apply()

优缺点分析:

  • 优点: 提供了统一的对象操作方法,与 Proxy 配合使用效果更佳。
  • 缺点: 浏览器支持情况可能不一致,需要使用 polyfill。

51. 数组的新方法与传统方法的性能对比

答案: ES6 数组的新方法(如 find()includes() 等)在性能上与传统方法(如 for 循环)相当,甚至在某些情况下更好,因为现代 JavaScript 引擎会对这些方法进行优化。

优缺点分析:

  • 优点: 代码更加简洁易读,开发效率更高。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 polyfill。

52. 字符串的新方法与传统方法的性能对比

答案: ES6 字符串的新方法(如 startsWith()endsWith() 等)在性能上与传统方法(如 indexOf())相当,甚至在某些情况下更好,因为现代 JavaScript 引擎会对这些方法进行优化。

优缺点分析:

  • 优点: 代码更加简洁易读,开发效率更高。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 polyfill。

53. 数值的新方法与传统方法的性能对比

答案: ES6 数值的新方法(如 Number.isInteger()Math.trunc() 等)在性能上与传统方法相当,甚至在某些情况下更好,因为现代 JavaScript 引擎会对这些方法进行优化。

优缺点分析:

  • 优点: 代码更加简洁易读,开发效率更高。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 polyfill。

54. 正则表达式的新特性与传统特性的性能对比

答案: ES6 正则表达式的新特性(如 Unicode 模式、粘性模式)在性能上与传统特性相当,甚至在某些情况下更好,因为现代 JavaScript 引擎会对这些特性进行优化。

优缺点分析:

  • 优点: 提供了更多功能,特别是对 Unicode 的支持。
  • 缺点: 在某些旧浏览器中可能不支持。

55. 解构赋值与传统赋值的性能对比

答案: 解构赋值在性能上与传统赋值相当,甚至在某些情况下更好,因为现代 JavaScript 引擎会对解构赋值进行优化。

优缺点分析:

  • 优点: 代码更加简洁易读,开发效率更高。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 Babel 等工具转译。

56. 扩展运算符与传统方法的性能对比

答案: 扩展运算符在性能上与传统方法(如 Array.prototype.concat())相当,甚至在某些情况下更好,因为现代 JavaScript 引擎会对扩展运算符进行优化。

优缺点分析:

  • 优点: 代码更加简洁易读,开发效率更高。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 Babel 等工具转译。

57. Promise 与回调函数的性能对比

答案: Promise 在性能上与回调函数相当,甚至在某些情况下更好,因为现代 JavaScript 引擎会对 Promise 进行优化。

优缺点分析:

  • 优点: 代码更加清晰易读,避免了回调地狱。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 polyfill。

58. async/await 与 Promise 的性能对比

答案: async/await 在性能上与 Promise 相当,因为 async/await 本质上是 Promise 的语法糖。

优缺点分析:

  • 优点: 代码更加简洁易读,看起来像同步代码。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 Babel 等工具转译。

59. 模块化与全局变量的性能对比

答案: 模块化在性能上与全局变量相当,甚至在某些情况下更好,因为模块化可以减少全局变量污染,提高代码可维护性。

优缺点分析:

  • 优点: 代码组织更加清晰,避免了全局变量污染。
  • 缺点: 在浏览器中需要使用打包工具或通过 <script type="module"> 标签支持。

60. 类与构造函数的性能对比

答案: 类在性能上与构造函数相当,因为类本质上是构造函数的语法糖。

优缺点分析:

  • 优点: 代码更加清晰易读,更接近传统面向对象语言。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 Babel 等工具转译。

61. let、const 与 var 的性能对比

答案: let、const 与 var 在性能上相当,因为现代 JavaScript 引擎会对它们进行优化。

优缺点分析:

  • let、const: 优点是作用域清晰,避免变量污染;缺点是在某些旧浏览器中可能不支持。
  • var: 优点是兼容性好;缺点是作用域混乱,容易导致变量污染。

62. 箭头函数与普通函数的性能对比

答案: 箭头函数与普通函数在性能上相当,因为现代 JavaScript 引擎会对它们进行优化。

优缺点分析:

  • 箭头函数: 优点是语法简洁,解决了 this 指向问题;缺点是功能相对受限。
  • 普通函数: 优点是功能完整,使用灵活;缺点是 this 指向可能会导致困惑。

63. Set 与 Array 的性能对比

答案: Set 在查找操作(has())上的性能比 Array(includes())好,因为 Set 使用哈希表实现,时间复杂度为 O(1),而 Array 的时间复杂度为 O(n)。

优缺点分析:

  • Set: 优点是查找速度快,自动去重;缺点是没有索引,操作不如 Array 灵活。
  • Array: 优点是操作灵活,有丰富的方法;缺点是查找速度较慢,需要手动去重。

64. Map 与 Object 的性能对比

答案: Map 在插入和删除操作上的性能比 Object 好,特别是当键值对数量较多时。

优缺点分析:

  • Map: 优点是键类型灵活,操作高效,保持插入顺序;缺点是语法稍复杂。
  • Object: 优点是语法简洁,使用方便;缺点是键类型受限,操作性能可能较差。

65. WeakSet 与 Set 的性能对比

答案: WeakSet 与 Set 在性能上相当,但 WeakSet 不会阻止垃圾回收,因此在某些情况下可能更节省内存。

优缺点分析:

  • WeakSet: 优点是有助于防止内存泄漏;缺点是功能相对受限,不能遍历。
  • Set: 优点是功能完整,支持遍历;缺点是可能会导致内存泄漏(如果存储了不再需要的对象)。

66. WeakMap 与 Map 的性能对比

答案: WeakMap 与 Map 在性能上相当,但 WeakMap 不会阻止垃圾回收,因此在某些情况下可能更节省内存。

优缺点分析:

  • WeakMap: 优点是有助于防止内存泄漏;缺点是功能相对受限,不能遍历。
  • Map: 优点是功能完整,支持遍历;缺点是可能会导致内存泄漏(如果存储了不再需要的对象)。

67. 生成器与普通函数的性能对比

答案: 生成器在性能上可能比普通函数稍差,因为生成器需要保存执行状态。

优缺点分析:

  • 生成器: 优点是提供了一种优雅的方式来处理迭代和异步操作;缺点是性能可能稍差,语法相对复杂。
  • 普通函数: 优点是性能较好,语法简单;缺点是处理迭代和异步操作可能不够优雅。

68. 代理(Proxy)与直接操作对象的性能对比

答案: 代理在性能上可能比直接操作对象稍差,因为代理需要拦截并处理对象操作。

优缺点分析:

  • 代理: 优点是提供了强大的对象操作拦截能力;缺点是性能可能稍差,在某些场景下可能会导致代码复杂度增加。
  • 直接操作对象: 优点是性能较好,代码简单;缺点是缺乏灵活性,无法实现高级功能。

69. 反射(Reflect)与直接操作对象的性能对比

答案: 反射在性能上与直接操作对象相当,因为反射只是提供了一种统一的对象操作方式。

优缺点分析:

  • 反射: 优点是提供了统一的对象操作方法,与 Proxy 配合使用效果更佳;缺点是浏览器支持情况可能不一致。
  • 直接操作对象: 优点是代码简单,浏览器支持好;缺点是缺乏统一的操作方式。

70. 模板字符串与字符串拼接的性能对比

答案: 模板字符串在性能上与字符串拼接相当,甚至在某些情况下更好,因为现代 JavaScript 引擎会对模板字符串进行优化。

优缺点分析:

  • 模板字符串: 优点是语法简洁,支持多行字符串;缺点是在某些旧浏览器中可能不支持。
  • 字符串拼接: 优点是兼容性好;缺点是语法繁琐,不支持多行字符串。

71. 默认参数与手动检查参数的性能对比

答案: 默认参数在性能上与手动检查参数相当,甚至在某些情况下更好,因为现代 JavaScript 引擎会对默认参数进行优化。

优缺点分析:

  • 默认参数: 优点是语法简洁,代码可读性高;缺点是在某些旧浏览器中可能不支持。
  • 手动检查参数: 优点是兼容性好;缺点是语法繁琐,代码可读性低。

72. 剩余参数与 arguments 对象的性能对比

答案: 剩余参数在性能上与 arguments 对象相当,甚至在某些情况下更好,因为剩余参数是一个真正的数组,而 arguments 是一个类数组对象。

优缺点分析:

  • 剩余参数: 优点是语法简洁,是真正的数组;缺点是在某些旧浏览器中可能不支持。
  • arguments 对象: 优点是兼容性好;缺点是是类数组对象,需要转换为数组才能使用数组方法。

73. 扩展运算符与数组方法的性能对比

答案: 扩展运算符在性能上与数组方法(如 Array.prototype.concat())相当,甚至在某些情况下更好,因为现代 JavaScript 引擎会对扩展运算符进行优化。

优缺点分析:

  • 扩展运算符: 优点是语法简洁,使用方便;缺点是在某些旧浏览器中可能不支持。
  • 数组方法: 优点是兼容性好;缺点是语法繁琐,代码可读性低。

74. Promise.all() 与顺序执行的性能对比

答案:Promise.all() 在处理多个异步操作时的性能比顺序执行好,因为它可以并行执行多个异步操作。

优缺点分析:

  • Promise.all(): 优点是并行执行,性能好;缺点是只要有一个 Promise 失败,整个操作就会失败。
  • 顺序执行: 优点是错误处理简单,操作顺序可控;缺点是性能较差,需要等待前一个操作完成。

75. Promise.race() 的应用场景

答案:Promise.race() 的应用场景包括:

  1. 超时处理:设置一个超时 Promise,与实际操作的 Promise 一起竞争
  2. 多源数据获取:从多个数据源获取数据,使用第一个返回的结果
  3. 并行操作的快速反馈:需要快速得到结果,不管是成功还是失败

优缺点分析:

  • 优点: 可以快速获取第一个完成的结果,适用于需要快速反馈的场景。
  • 缺点: 只返回第一个完成的结果,可能会忽略其他结果。

76. Promise.allSettled() 的应用场景

答案:Promise.allSettled() 的应用场景包括:

  1. 并行执行多个异步操作,不管成功还是失败
  2. 需要获取所有操作的结果,包括成功和失败的
  3. 错误处理更加灵活,不会因为一个操作失败而影响其他操作

优缺点分析:

  • 优点: 可以获取所有操作的结果,错误处理更加灵活。
  • 缺点: 在某些旧浏览器中可能不支持。

77. Promise.any() 的应用场景

答案:Promise.any() 的应用场景包括:

  1. 从多个数据源获取数据,使用第一个成功的结果
  2. 容错处理:只要有一个操作成功,整个操作就成功
  3. 提高系统可用性:尝试多个服务,使用第一个响应的

优缺点分析:

  • 优点: 只要有一个操作成功,整个操作就成功,提高了系统的可用性。
  • 缺点: 在某些旧浏览器中可能不支持。

78. 动态导入(import())的应用场景

答案: 动态导入的应用场景包括:

  1. 代码分割:按需加载代码,减少初始加载时间
  2. 条件加载:根据条件加载不同的模块
  3. 懒加载:当需要时才加载模块

优缺点分析:

  • 优点: 可以减少初始加载时间,提高应用性能。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用打包工具。

79. 类的私有字段的应用场景

答案: 类的私有字段的应用场景包括:

  1. 封装内部状态:防止外部直接访问和修改
  2. 保护敏感数据:如密码、API 密钥等
  3. 避免命名冲突:私有字段不会与外部变量冲突

优缺点分析:

  • 优点: 提供了真正的封装,保护内部状态。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 Babel 等工具转译。

80. 类的 getter 和 setter 的应用场景

答案: 类的 getter 和 setter 的应用场景包括:

  1. 数据验证:在设置属性时进行验证
  2. 计算属性:根据其他属性计算得出的值
  3. 懒加载:在需要时才计算值
  4. 封装内部状态:提供访问内部状态的接口

优缺点分析:

  • 优点: 提供了对属性访问和修改的控制,增加了代码的灵活性。
  • 缺点: 可能会导致性能开销(如果 getter 或 setter 中有复杂逻辑)。

81. 箭头函数在回调中的应用

答案: 箭头函数在回调中的应用非常广泛,特别是在需要保持 this 指向的场景:

javascript
// 传统函数
const obj = {
  name: 'John',
  greet: function () {
    setTimeout(function () {
      console.log(`Hello, ${this.name}!`) // 输出: Hello, undefined!
    }, 1000)
  }
}

// 箭头函数
const obj = {
  name: 'John',
  greet: function () {
    setTimeout(() => {
      console.log(`Hello, ${this.name}!`) // 输出: Hello, John!
    }, 1000)
  }
}

优缺点分析:

  • 优点: 解决了回调函数中 this 指向的问题,代码更加简洁。
  • 缺点: 在某些需要动态 this 的场景下可能不适用。

82. 解构赋值在函数参数中的应用

答案: 解构赋值在函数参数中的应用可以使代码更加简洁:

javascript
// 传统方式
function greet(person) {
  const name = person.name
  const age = person.age
  return `Hello, ${name}, you are ${age} years old.`
}

// 使用解构赋值
function greet({ name, age }) {
  return `Hello, ${name}, you are ${age} years old.`
}

优缺点分析:

  • 优点: 代码更加简洁,参数结构更加清晰。
  • 缺点: 如果参数是 undefined 或 null,会抛出错误(需要设置默认值)。

83. 扩展运算符在函数调用中的应用

答案: 扩展运算符在函数调用中的应用可以使代码更加简洁:

javascript
function sum(a, b, c) {
  return a + b + c
}

const numbers = [1, 2, 3]

// 传统方式
sum(numbers[0], numbers[1], numbers[2])

// 使用扩展运算符
sum(...numbers)

优缺点分析:

  • 优点: 代码更加简洁,避免了手动索引。
  • 缺点: 在某些旧浏览器中可能不支持。

84. 模板字符串在 HTML 模板中的应用

答案: 模板字符串在 HTML 模板中的应用可以使代码更加简洁:

javascript
const name = 'John'
const age = 30

// 传统方式
const html = '<div><h1>' + name + '</h1><p>Age: ' + age + '</p></div>'

// 使用模板字符串
const html = `<div><h1>${name}</h1><p>Age: ${age}</p></div>`

优缺点分析:

  • 优点: 代码更加简洁,支持多行字符串,避免了字符串拼接的繁琐。
  • 缺点: 在某些旧浏览器中可能不支持。

85. 模块化在大型项目中的应用

答案: 模块化在大型项目中的应用可以使代码组织更加清晰:

  1. 按功能划分模块
  2. 避免全局变量污染
  3. 提高代码复用性
  4. 便于团队协作
  5. 有利于代码维护和测试

优缺点分析:

  • 优点: 代码组织更加清晰,提高了代码可维护性和复用性。
  • 缺点: 需要使用打包工具,配置可能比较复杂。

86. Promise 在异步操作中的应用

答案: Promise 在异步操作中的应用非常广泛,如:

  1. 网络请求:fetch() API 返回 Promise
  2. 文件操作:Node.js 中的文件操作可以包装为 Promise
  3. 定时器:setTimeout() 可以包装为 Promise
  4. 数据库操作:数据库查询可以包装为 Promise

优缺点分析:

  • 优点: 解决了回调地狱问题,使异步代码更加清晰易读。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 polyfill。

87. async/await 在异步操作中的应用

答案: async/await 在异步操作中的应用可以使代码更加简洁:

javascript
// 使用 Promise
function fetchData() {
  return fetch('https://api.example.com/data')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error))
}

// 使用 async/await
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data')
    const data = await response.json()
    console.log(data)
  } catch (error) {
    console.error(error)
  }
}

优缺点分析:

  • 优点: 代码更加简洁,看起来像同步代码,错误处理更加直观。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用 Babel 等工具转译。

88. Set 在数组去重中的应用

答案: Set 在数组去重中的应用非常简洁:

javascript
const array = [1, 2, 3, 3, 2, 1]
const uniqueArray = [...new Set(array)] // [1, 2, 3]

优缺点分析:

  • 优点: 代码简洁,执行效率高。
  • 缺点: 在某些旧浏览器中可能不支持。

89. Map 在缓存中的应用

答案: Map 在缓存中的应用可以提高数据访问速度:

javascript
const cache = new Map()

function getData(key) {
  if (cache.has(key)) {
    return cache.get(key)
  }

  const data = fetchDataFromServer(key)
  cache.set(key, data)
  return data
}

优缺点分析:

  • 优点: 缓存操作简洁,查找速度快。
  • 缺点: 在某些旧浏览器中可能不支持。

90. WeakMap 在私有属性中的应用

答案: WeakMap 在私有属性中的应用可以避免内存泄漏:

javascript
const privateProps = new WeakMap()

class Person {
  constructor(name) {
    privateProps.set(this, { name })
  }

  get name() {
    return privateProps.get(this).name
  }
}

优缺点分析:

  • 优点: 实现了真正的私有属性,避免了内存泄漏。
  • 缺点: 语法稍复杂,在某些旧浏览器中可能不支持。

91. 生成器在异步迭代中的应用

答案: 生成器在异步迭代中的应用可以使代码更加清晰:

javascript
function* asyncGenerator() {
  yield fetch('https://api.example.com/data1')
  yield fetch('https://api.example.com/data2')
  yield fetch('https://api.example.com/data3')
}

async function processData() {
  for await (const response of asyncGenerator()) {
    const data = await response.json()
    console.log(data)
  }
}

优缺点分析:

  • 优点: 代码更加清晰,便于处理异步迭代。
  • 缺点: 语法相对复杂,在某些旧浏览器中可能不支持。

92. 代理(Proxy)在数据验证中的应用

答案: 代理在数据验证中的应用可以确保数据的有效性:

javascript
const validator = {
  set(target, prop, value) {
    if (prop === 'age') {
      if (typeof value !== 'number' || value < 0) {
        throw new Error('Age must be a positive number')
      }
    }
    target[prop] = value
    return true
  }
}

const person = new Proxy({}, validator)
person.age = 30 // 正确
person.age = -5 // 抛出错误

优缺点分析:

  • 优点: 可以在数据设置时进行验证,确保数据的有效性。
  • 缺点: 性能可能稍差,在某些旧浏览器中可能不支持。

93. 反射(Reflect)在动态操作中的应用

答案: 反射在动态操作中的应用可以使代码更加灵活:

javascript
const obj = { name: 'John', age: 30 }

// 动态获取属性
const prop = 'name'
console.log(Reflect.get(obj, prop)) // 输出: John

// 动态设置属性
Reflect.set(obj, 'age', 31)
console.log(obj.age) // 输出: 31

// 动态检查属性是否存在
console.log(Reflect.has(obj, 'name')) // 输出: true

优缺点分析:

  • 优点: 提供了统一的动态操作方法,使代码更加灵活。
  • 缺点: 在某些旧浏览器中可能不支持。

94. 数组的新方法在数据处理中的应用

答案: 数组的新方法在数据处理中的应用非常广泛,如:

  1. find():查找第一个满足条件的元素
  2. filter():过滤出满足条件的元素
  3. map():对数组中的每个元素进行操作
  4. reduce():将数组元素归约为一个值
  5. includes():判断数组是否包含某个元素

优缺点分析:

  • 优点: 代码更加简洁易读,开发效率更高。
  • 缺点: 在某些旧浏览器中可能不支持。

95. 字符串的新方法在文本处理中的应用

答案: 字符串的新方法在文本处理中的应用非常广泛,如:

  1. startsWith():判断字符串是否以指定字符开始
  2. endsWith():判断字符串是否以指定字符结束
  3. includes():判断字符串是否包含指定字符
  4. repeat():重复字符串指定次数

优缺点分析:

  • 优点: 代码更加简洁易读,开发效率更高。
  • 缺点: 在某些旧浏览器中可能不支持。

96. 数值的新方法在数学计算中的应用

答案: 数值的新方法在数学计算中的应用非常广泛,如:

  1. Number.isFinite():判断一个数是否是有限的
  2. Number.isNaN():判断一个值是否是 NaN
  3. Number.isInteger():判断一个数是否是整数
  4. Math.trunc():去除小数部分
  5. Math.sign():返回数字的符号

优缺点分析:

  • 优点: 代码更加简洁易读,开发效率更高。
  • 缺点: 在某些旧浏览器中可能不支持。

97. 正则表达式的新特性在模式匹配中的应用

答案: 正则表达式的新特性在模式匹配中的应用非常广泛,如:

  1. Unicode 模式:正确处理 Unicode 字符
  2. 粘性模式:从目标字符串的当前位置开始匹配

优缺点分析:

  • 优点: 提供了更多功能,特别是对 Unicode 的支持。
  • 缺点: 在某些旧浏览器中可能不支持。

98. 解构赋值在模块导入中的应用

答案: 解构赋值在模块导入中的应用可以使代码更加简洁:

javascript
// 传统方式
import module from './module.js'
const name = module.name
const greet = module.greet

// 使用解构赋值
import { name, greet } from './module.js'

优缺点分析:

  • 优点: 代码更加简洁,只导入需要的部分。
  • 缺点: 在某些旧浏览器中可能不支持,需要使用打包工具。

99. 扩展运算符在对象合并中的应用

答案: 扩展运算符在对象合并中的应用可以使代码更加简洁:

javascript
const obj1 = { a: 1, b: 2 }
const obj2 = { c: 3, d: 4 }

// 传统方式
const mergedObj = Object.assign({}, obj1, obj2)

// 使用扩展运算符
const mergedObj = { ...obj1, ...obj2 }

优缺点分析:

  • 优点: 代码更加简洁,使用方便。
  • 缺点: 在某些旧浏览器中可能不支持。

100. ES6 特性的浏览器兼容性

答案: ES6 特性的浏览器兼容性情况:

  1. 现代浏览器(Chrome、Firefox、Safari、Edge)基本支持所有 ES6 特性
  2. 旧浏览器(如 IE11)不支持大部分 ES6 特性
  3. 可以使用 Babel 等工具将 ES6 代码转译为 ES5,以支持旧浏览器
  4. 可以使用 polyfill 来模拟 ES6 特性在旧浏览器中的行为

优缺点分析:

  • 优点: 现代浏览器支持良好,提供了丰富的新特性。
  • 缺点: 旧浏览器支持较差,需要使用转译工具和 polyfill。

基于 VitePress 的本地知识库