Appearance
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 中引入的一种新的函数声明方式作用是消除函数的二义性,具有以下特点:
- 语法简洁,使用
=>符号定义 - 没有自己的
this,会继承父级作用域的this - 不能作为构造函数使用
- 没有
arguments对象 - 不能使用
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. 剩余参数和扩展运算符
答案:
剩余参数: 使用
...收集剩余的参数到一个数组中:javascriptfunction sum(...numbers) { return numbers.reduce((total, num) => total + num, 0) }扩展运算符: 使用
...将数组或对象展开:javascriptconst 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 引入了模块化系统,使用 import 和 export 关键字:
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: 存储唯一值的集合,不允许重复元素。
javascriptconst set = new Set([1, 2, 3, 3]) console.log(set.size) // 输出: 3Map: 存储键值对的集合,键可以是任意类型。
javascriptconst 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():判断一个值是否是 NaNNumber.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():等待第一个完成的 PromisePromise.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. 箭头函数与普通函数的区别
答案: 箭头函数与普通函数的主要区别:
- 语法不同:箭头函数使用
=>符号 this指向不同:箭头函数继承父级作用域的this,普通函数的this取决于调用方式- 构造函数:箭头函数不能作为构造函数,普通函数可以
arguments对象:箭头函数没有arguments对象,普通函数有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 的主要区别:
- 语法不同:ES6 使用
import/export,CommonJS 使用require/module.exports - 加载方式不同:ES6 是静态加载(编译时),CommonJS 是动态加载(运行时)
- 适用环境不同:ES6 模块化适用于浏览器和 Node.js,CommonJS 主要适用于 Node.js
优缺点分析:
- ES6 模块化: 优点是静态加载,有利于树摇和类型检查;缺点是在某些环境中需要转译。
- CommonJS: 优点是动态加载,灵活性高;缺点是不利于树摇。
38. Set 和 Array 的区别
答案: Set 和 Array 的主要区别:
- Set 存储唯一值,Array 可以存储重复值
- Set 没有索引,Array 有索引
- Set 的查找速度比 Array 快(时间复杂度 O(1) vs O(n))
- Set 没有
push、pop等方法,需要使用add、delete等方法
优缺点分析:
- Set: 优点是自动去重,查找速度快;缺点是没有索引,操作不如 Array 灵活。
- Array: 优点是操作灵活,有丰富的方法;缺点是需要手动去重,查找速度较慢。
39. Map 和 Object 的区别
答案: Map 和 Object 的主要区别:
- Map 的键可以是任意类型,Object 的键只能是字符串或 Symbol
- Map 的大小可以通过
size属性获取,Object 的大小需要手动计算 - Map 是可迭代的,Object 需要通过
Object.keys()等方法才能迭代 - Map 的插入和删除操作性能更好
优缺点分析:
- Map: 优点是键类型灵活,大小可直接获取,迭代方便;缺点是操作稍复杂。
- Object: 优点是语法简洁,使用方便;缺点是键类型受限,大小需要手动计算。
40. 箭头函数中的 this 指向
答案: 箭头函数没有自己的 this,它会继承父级作用域的 this。这意味着箭头函数中的 this 指向在定义时就已经确定,不会受到调用方式的影响。
优缺点分析:
- 优点: 解决了传统函数中
this指向不确定的问题,使代码更加可预测。 - 缺点: 在某些需要动态
this的场景下可能不适用。
41. 类的继承与原型继承的关系
答案: ES6 类的继承本质上是原型继承的语法糖。当使用 class A extends B 时,A 的原型会指向 B 的实例,从而实现继承。
优缺点分析:
- 优点: 语法更加清晰,更接近传统面向对象语言。
- 缺点: 可能会让开发者误以为 JavaScript 是真正的面向对象语言,而忽略其原型继承的本质。
42. Promise 的状态变化
答案: Promise 有三种状态:
- pending(进行中):初始状态,既不是成功也不是失败
- fulfilled(已成功):操作成功完成
- rejected(已失败):操作失败
Promise 的状态一旦改变,就不会再变。
优缺点分析:
- 优点: 状态管理清晰,避免了回调地狱。
- 缺点: 一旦创建就无法取消,可能会导致内存泄漏(如果 Promise 永远不 resolve 或 reject)。
43. async/await 的错误处理最佳实践
答案: async/await 的错误处理最佳实践:
- 使用 try/catch 捕获错误
- 对于可能失败的操作,始终使用 try/catch 包裹
- 可以在 catch 块中进行错误处理或向上抛出
- 对于多个异步操作,可以使用 Promise.all() 配合 try/catch
优缺点分析:
- 优点: 错误处理更加直观,代码更加清晰。
- 缺点: 如果忘记添加 try/catch,错误可能会被静默忽略。
44. 模块化的树摇(Tree Shaking)
答案: 树摇是指在打包过程中,移除未使用的代码。ES6 模块化的静态加载特性使得树摇成为可能,因为打包工具可以在编译时确定哪些代码被使用,哪些代码未被使用。
优缺点分析:
- 优点: 减少打包体积,提高应用性能。
- 缺点: 依赖于打包工具的实现,可能需要特定的配置。
45. Set 的应用场景
答案: Set 的应用场景包括:
- 数组去重:
const uniqueArray = [...new Set(array)] - 存储唯一值:如用户 ID、标签等
- 检查值是否存在:
set.has(value) - 遍历操作:使用
for...of循环
优缺点分析:
- 优点: 自动去重,查找速度快,操作简洁。
- 缺点: 没有索引,不能直接访问元素。
46. Map 的应用场景
答案: Map 的应用场景包括:
- 存储键值对,其中键不是字符串:如对象作为键
- 需要频繁添加和删除键值对的场景
- 需要获取键值对数量的场景:
map.size - 需要保持插入顺序的场景:Map 会保持键值对的插入顺序
优缺点分析:
- 优点: 键类型灵活,操作高效,保持插入顺序。
- 缺点: 语法稍复杂,在某些旧浏览器中不支持。
47. WeakSet 和 WeakMap 的应用场景
答案: WeakSet 和 WeakMap 的应用场景包括:
- 存储临时对象:当对象没有其他引用时会被垃圾回收
- 避免内存泄漏:如缓存、事件监听器等
- 存储与对象相关的元数据:不影响对象的垃圾回收
优缺点分析:
- 优点: 有助于防止内存泄漏,适合存储临时数据。
- 缺点: 不能遍历,不能获取大小,功能相对受限。
48. 生成器的应用场景
答案: 生成器的应用场景包括:
- 惰性计算:按需生成值,节省内存
- 异步操作:使用 co 库或 async/await
- 迭代器实现:自定义可迭代对象
- 状态管理:保存函数执行状态
优缺点分析:
- 优点: 提供了一种优雅的方式来处理迭代和异步操作。
- 缺点: 语法相对复杂,可能对初学者来说难以理解。
49. 代理(Proxy)的应用场景
答案: 代理的应用场景包括:
- 数据验证:拦截并验证属性赋值
- 日志记录:记录对象的操作
- 数据绑定:实现响应式数据
- 私有属性:模拟私有属性
- 缓存:缓存对象的操作结果
优缺点分析:
- 优点: 提供了强大的对象操作拦截能力,可用于实现各种高级功能。
- 缺点: 性能可能比直接操作对象稍差,在某些场景下可能会导致代码复杂度增加。
50. 反射(Reflect)的应用场景
答案: 反射的应用场景包括:
- 与 Proxy 配合使用:提供统一的对象操作方法
- 动态操作对象:如动态获取、设置属性
- 检查对象属性:如
Reflect.has()、Reflect.ownKeys() - 调用函数:
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() 的应用场景包括:
- 超时处理:设置一个超时 Promise,与实际操作的 Promise 一起竞争
- 多源数据获取:从多个数据源获取数据,使用第一个返回的结果
- 并行操作的快速反馈:需要快速得到结果,不管是成功还是失败
优缺点分析:
- 优点: 可以快速获取第一个完成的结果,适用于需要快速反馈的场景。
- 缺点: 只返回第一个完成的结果,可能会忽略其他结果。
76. Promise.allSettled() 的应用场景
答案:Promise.allSettled() 的应用场景包括:
- 并行执行多个异步操作,不管成功还是失败
- 需要获取所有操作的结果,包括成功和失败的
- 错误处理更加灵活,不会因为一个操作失败而影响其他操作
优缺点分析:
- 优点: 可以获取所有操作的结果,错误处理更加灵活。
- 缺点: 在某些旧浏览器中可能不支持。
77. Promise.any() 的应用场景
答案:Promise.any() 的应用场景包括:
- 从多个数据源获取数据,使用第一个成功的结果
- 容错处理:只要有一个操作成功,整个操作就成功
- 提高系统可用性:尝试多个服务,使用第一个响应的
优缺点分析:
- 优点: 只要有一个操作成功,整个操作就成功,提高了系统的可用性。
- 缺点: 在某些旧浏览器中可能不支持。
78. 动态导入(import())的应用场景
答案: 动态导入的应用场景包括:
- 代码分割:按需加载代码,减少初始加载时间
- 条件加载:根据条件加载不同的模块
- 懒加载:当需要时才加载模块
优缺点分析:
- 优点: 可以减少初始加载时间,提高应用性能。
- 缺点: 在某些旧浏览器中可能不支持,需要使用打包工具。
79. 类的私有字段的应用场景
答案: 类的私有字段的应用场景包括:
- 封装内部状态:防止外部直接访问和修改
- 保护敏感数据:如密码、API 密钥等
- 避免命名冲突:私有字段不会与外部变量冲突
优缺点分析:
- 优点: 提供了真正的封装,保护内部状态。
- 缺点: 在某些旧浏览器中可能不支持,需要使用 Babel 等工具转译。
80. 类的 getter 和 setter 的应用场景
答案: 类的 getter 和 setter 的应用场景包括:
- 数据验证:在设置属性时进行验证
- 计算属性:根据其他属性计算得出的值
- 懒加载:在需要时才计算值
- 封装内部状态:提供访问内部状态的接口
优缺点分析:
- 优点: 提供了对属性访问和修改的控制,增加了代码的灵活性。
- 缺点: 可能会导致性能开销(如果 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. 模块化在大型项目中的应用
答案: 模块化在大型项目中的应用可以使代码组织更加清晰:
- 按功能划分模块
- 避免全局变量污染
- 提高代码复用性
- 便于团队协作
- 有利于代码维护和测试
优缺点分析:
- 优点: 代码组织更加清晰,提高了代码可维护性和复用性。
- 缺点: 需要使用打包工具,配置可能比较复杂。
86. Promise 在异步操作中的应用
答案: Promise 在异步操作中的应用非常广泛,如:
- 网络请求:
fetch()API 返回 Promise - 文件操作:Node.js 中的文件操作可以包装为 Promise
- 定时器:
setTimeout()可以包装为 Promise - 数据库操作:数据库查询可以包装为 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. 数组的新方法在数据处理中的应用
答案: 数组的新方法在数据处理中的应用非常广泛,如:
find():查找第一个满足条件的元素filter():过滤出满足条件的元素map():对数组中的每个元素进行操作reduce():将数组元素归约为一个值includes():判断数组是否包含某个元素
优缺点分析:
- 优点: 代码更加简洁易读,开发效率更高。
- 缺点: 在某些旧浏览器中可能不支持。
95. 字符串的新方法在文本处理中的应用
答案: 字符串的新方法在文本处理中的应用非常广泛,如:
startsWith():判断字符串是否以指定字符开始endsWith():判断字符串是否以指定字符结束includes():判断字符串是否包含指定字符repeat():重复字符串指定次数
优缺点分析:
- 优点: 代码更加简洁易读,开发效率更高。
- 缺点: 在某些旧浏览器中可能不支持。
96. 数值的新方法在数学计算中的应用
答案: 数值的新方法在数学计算中的应用非常广泛,如:
Number.isFinite():判断一个数是否是有限的Number.isNaN():判断一个值是否是 NaNNumber.isInteger():判断一个数是否是整数Math.trunc():去除小数部分Math.sign():返回数字的符号
优缺点分析:
- 优点: 代码更加简洁易读,开发效率更高。
- 缺点: 在某些旧浏览器中可能不支持。
97. 正则表达式的新特性在模式匹配中的应用
答案: 正则表达式的新特性在模式匹配中的应用非常广泛,如:
- Unicode 模式:正确处理 Unicode 字符
- 粘性模式:从目标字符串的当前位置开始匹配
优缺点分析:
- 优点: 提供了更多功能,特别是对 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 特性的浏览器兼容性情况:
- 现代浏览器(Chrome、Firefox、Safari、Edge)基本支持所有 ES6 特性
- 旧浏览器(如 IE11)不支持大部分 ES6 特性
- 可以使用 Babel 等工具将 ES6 代码转译为 ES5,以支持旧浏览器
- 可以使用 polyfill 来模拟 ES6 特性在旧浏览器中的行为
优缺点分析:
- 优点: 现代浏览器支持良好,提供了丰富的新特性。
- 缺点: 旧浏览器支持较差,需要使用转译工具和 polyfill。