以下是老曹关于 ES6(ECMAScript 2015)最常用的 20 道面试题总结,涵盖 let/const
、箭头函数、解构赋值、模板字符串、类、模块、Promise 等核心特性。每道题都配有详细解释和代码示例,适合前端开发岗位的 JavaScript 技术面试准备,最后还有ES2025最前沿的技术和面试题准备,大家可以码住随时翻出来查阅背诵和练习!
1. let
和 const
与 var
的区别?
问题: 写出 let
、const
和 var
在作用域、提升、重复声明方面的区别。
答案:
特性 | var | let | const |
---|---|---|---|
作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
提升(Hoisting) | 是(初始化为 undefined ) | 否(TDZ 暂时性死区) | 否(TDZ) |
可重新赋值 | ✅ | ✅ | ❌(常量不可变) |
可重复声明 | ✅ | ❌ | ❌ |
if (true) {
var a = 1;
let b = 2;
const c = 3;
}
console.log(a); // 输出: 1
console.log(b); // 报错: b is not defined
2. 箭头函数与普通函数的区别?
问题: 箭头函数中的 this
如何绑定?
答案:
- 箭头函数没有自己的
this
,继承外层作用域的this
。 - 不可以作为构造函数(不能用
new
调用)。 - 没有
arguments
对象。
const obj = {
name: "Alice",
greet: () => {
console.log(this.name); // undefined,因为 this 继承自全局对象
}
};
obj.greet();
3. 解构赋值的作用是什么?如何使用?
问题: 从对象中提取 name和 age
属性。
答案:
用于从数组或对象中快速提取数据。
const person = { name: "Tom", age: 25 };
const { name, age } = person;
console.log(name); // Tom
console.log(age); // 25
4. 模板字符串有什么优势?如何使用?
问题: 使用模板字符串拼接 name和 age
。
答案:
支持多行字符串和变量插入。
const name = "Jerry";
const age = 30;
console.log(`Name: ${name}, Age: ${age}`);
// 输出: Name: Jerry, Age: 30
5. 默认参数值的作用是什么?如何使用?
问题: 写一个函数,参数未传时使用默认值。
答案:
function greet(name = "Guest") {
console.log("Hello, " + name);
}
greet(); // Hello, Guest
greet("Alice"); // Hello, Alice
6. 扩展运算符(...
)有哪些用途?
问题: 合并两个数组,并添加新元素。
答案:
- 数组合并。
- 参数展开。
- 克隆对象/数组。
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = [...arr1, ...arr2, 5];
console.log(combined); // [1, 2, 3, 4, 5]
7. Map
和 Object
的区别?
问题: 列举 Map
相比 Object
的优势。
答案:
特性 | Object | Map |
---|---|---|
键类型 | 只能是字符串 | 可以是任意类型 |
顺序 | 无序(ES5) | 保持插入顺序 |
可迭代 | ❌ | ✅ |
获取大小 | ❌ | ✅ .size |
const map = new Map();
map.set("key", "value");
map.set(123, "number key");
console.log(map.get(123)); // number key
8. Set
的作用是什么?如何去重?
问题: 使用 Set
实现数组去重。
答案:
Set
是存储唯一值的集合。
const arr = [1, 2, 2, 3, 4, 4, 5];
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // [1, 2, 3, 4, 5]
9. 类的基本语法是什么?如何定义一个类?
问题: 定义一个 Person
类,包含构造函数和方法。
答案:
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, I'm ${this.name}`);
}
}
const p = new Person("Bob");
p.sayHello(); // Hello, I'm Bob
10. super()
和 extends
的作用是什么?
问题: 子类中调用父类的构造函数。
答案:
extends
:实现类的继承。super()
:调用父类的构造函数。
class Animal {
constructor(name) {
this.name = name;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父类构造函数
this.breed = breed;
}
}
const d = new Dog("Buddy", "Golden");
console.log(d.name); // Buddy
console.log(d.breed); // Golden
11. Symbol
是什么?如何创建唯一的 Symbol?
问题: 创建两个不相等的 Symbol
。
答案:
Symbol
是一种原始数据类型,表示独一无二的值。
const sym1 = Symbol('id');
const sym2 = Symbol('id');
console.log(sym1 === sym2); // false
12. 迭代器(Iterator)和 for...of
循环的关系?
问题: 使用 for...of
遍历数组。
答案:
for...of
会自动调用对象的 [Symbol.iterator]()
方法。
const arr = [1, 2, 3];
for (let item of arr) {
console.log(item); // 输出: 1, 2, 3
}
13. Proxy
是什么?有什么用途?
问题: 使用 Proxy
实现属性访问拦截。
答案:
Proxy
用于定义基本操作的自定义行为(如属性查找、赋值、枚举等)。
const target = {
message: 'Hello'
};
const handler = {
get(target, prop) {
if (prop in target) {
return target[prop];
}
return 'Property not found';
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.message); // Hello
console.log(proxy.age); // Property not found
14. Promise
的状态有哪些?如何使用?
问题: 写一个异步请求的 Promise
示例。
答案:
状态:pending
→ fulfilled
或 rejected
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data fetched!");
}, 1000);
});
};
fetchData()
.then(data => console.log(data)) // Data fetched!
.catch(error => console.error(error));
15. async/await
的作用是什么?如何使用?
问题: 使用 async/await
替代 Promise.then()
。
答案:
让异步代码看起来像同步代码。
async function getData() {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error(error);
}
}
getData();
16. Array.from()
和 Array.prototype.slice.call()
的区别?
问题: 将类数组转换为数组。
答案:
Array.from()
更简洁且兼容性好。slice.call()
是 ES5 中的替代方式。
const arrayLike = { 0: 'a', 1: 'b', length: 2 };
const arr1 = Array.from(arrayLike);
console.log(arr1); // ['a', 'b']
const arr2 = Array.prototype.slice.call(arrayLike);
console.log(arr2); // ['a', 'b']
17. Object.assign()
的用途是什么?是否是深拷贝?
问题: 合并多个对象到目标对象中。
答案:
浅拷贝,嵌套对象引用不会复制。
const target = { a: 1 };
const source = { b: 2 };
const merged = Object.assign(target, source);
console.log(merged); // { a: 1, b: 2 }
18. import
和 export
的基本用法?
问题: 导出一个函数并在另一个文件中导入。
答案:
// math.js
export function add(a, b) {
return a + b;
}
// main.js
import { add } from './math.js';
console.log(add(2, 3)); // 5
19. Reflect
对象的作用是什么?有哪些常用方法?
问题: 使用 Reflect.set()
设置对象属性。
答案:
Reflect
是一组内置方法,提供更底层的操作接口。
const obj = {};
Reflect.set(obj, 'name', 'Alice');
console.log(obj.name); // Alice
20. Generator
函数的作用是什么?如何使用?
问题: 写一个生成器函数,每次调用返回下一个数。
答案:
function*
定义生成器函数,通过 yield
控制流程。
function* counter() {
yield 1;
yield 2;
yield 3;
}
const gen = counter();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
📋 总结表格
编号 | 题目描述 | 知识点 | 示例代码 | 常见考察点 |
---|---|---|---|---|
1 | let / const vs var | 块级作用域 | let count = 0; | 变量作用域 |
2 | 箭头函数 | this 绑定 | () => {} | 上下文理解 |
3 | 解构赋值 | 数据提取 | const { name } = obj | 数据处理 |
4 | 模板字符串 | 多行 + 插值 | `Hello ${name}` | 字符串拼接 |
5 | 默认参数 | 函数参数默认值 | function greet(name = 'Guest') | 函数设计 |
6 | 扩展运算符 | 展开/合并 | ...arr | 数组/对象操作 |
7 | Map vs Object | 键值对结构 | new Map() | 数据结构选择 |
8 | Set 去重 | 唯一值集合 | new Set([1, 2, 2]) | 去重优化 |
9 | 类定义 | OOP 支持 | class Person {} | 面向对象 |
10 | super() 和 extends | 类继承 | super(name) | 继承机制 |
11 | Symbol | 唯一标识符 | Symbol('id') | 数据唯一性 |
12 | for...of | 可迭代协议 | for (let item of arr) | 遍历控制 |
13 | Proxy | 拦截操作 | new Proxy(obj, handler) | 元编程 |
14 | Promise 状态 | 异步处理 | new Promise(...) | 异步编程 |
15 | async/await | 异步语法糖 | async function foo() { await bar(); } | 异步流程控制 |
16 | Array.from() | 类数组转数组 | Array.from(arrayLike) | DOM 操作 |
17 | Object.assign() | 浅拷贝 | Object.assign(target, source) | 对象合并 |
18 | import/export | 模块系统 | export function foo() , import { foo } from 'module' | 模块化开发 |
19 | Reflect | 元操作 | Reflect.set(obj, 'key', value) | 底层 API |
20 | Generator 函数 | 暂停执行 | function* gen() { yield 1; } | 控制流 |
以下是ES2025(即 ECMAScript 2025) 可选链、模式匹配、Top-level await、Temporal API 等最新标准内容。是老曹从MDN文档上最新发布的提案中扒下来总结出来成为面试题的,大家可以按需记忆,到时候给面试官一点小小的ES震撼!
1. 可选链(Optional Chaining)?.
的作用是什么?
问题: 安全访问嵌套对象属性。
答案:
防止访问 undefined
或 null
的属性时报错。
const user = {
profile: {
name: "John"
}
};
console.log(user.profile?.name); // John
console.log(user.settings?.theme); // undefined(不会报错)
2. 空值合并运算符(Nullish Coalescing)??
的作用是什么?
问题: 如果值为 null
或 undefined
,则返回默认值。
答案:
仅当左侧为 null
或 undefined
时才使用右侧值。
const value = null ?? "default";
console.log(value); // default
const count = 0 ?? 100;
console.log(count); // 0(不同于 || 的逻辑)
3. Top-level await
的作用是什么?
问题: 在模块顶层使用 await
是否合法?
答案:
在模块中可以直接在顶层使用 await
,无需包裹在 async
函数中。
// main.js(需作为模块加载)
const response = await fetch('https://api.example.com/data');
const data = await response.json();
export { data };
4. Temporal
API(ES2025 新增)的作用是什么?
问题: 使用新的 Temporal
API 格式化日期时间。
答案:
Temporal
是 ECMA TC39 提案(预计 ES2025 正式纳入),提供现代化、安全、易用的时间处理接口。
// 注意:目前浏览器可能未完全支持,需 polyfill 或 Node.js 支持
import { Temporal } from 'proposal-temporal';
const now = Temporal.Now.instant();
const zoned = now.toZonedDateTimeISO(Temporal.Now.timeZone());
console.log(zoned.toString()); // 输出 ISO 格式时间(带时区)
📌 ECMAScript 最新技术(至 2025 年新增特性)
特性 | 描述 | 示例 |
---|---|---|
模式匹配(Pattern Matching) | 类似 Rust 的 match 表达式 | match (value) { when 1 => 'one' } |
Top-level await | 模块顶层支持 await | const data = await fetch(...) |
Temporal API | 新一代日期时间库 | Temporal.Now.instant() |
Records & Tuples(实验阶段) | 不可变数据结构 | #{ x: 1, y: 2 } |
装饰器(Decorators) | 支持类、方法、字段装饰 | @log class MyClass {} |
私有字段(Private Fields) | 使用 #field 声明私有成员 | class Counter { #count = 0; } |
Promise.try / catchChain / finally | 异步流程控制 | Promise.try(() => {...}) |
Intl.DateTimeFormat.formatToParts | 国际化日期格式 | formatter.formatToParts(date) |
WeakRefs & FinalizationRegistry | 弱引用和垃圾回收追踪 | const ref = new WeakRef(obj) |
**Pipeline operator( | >)** | 函数链式调用(Stage 1) |
📋 总结表格(最新特性)
编号 | 题目描述 | 知识点 | 示例代码 | 常见考察点 |
---|---|---|---|---|
1 | 可选链 ?. | 安全访问嵌套属性 | user?.address?.city | 空值防御 |
2 | 空值合并 ?? | 默认值控制 | value ?? 'default' | 默认值逻辑 |
3 | Top-level await | 模块级异步 | const data = await fetch(...) | 异步模块 |
4 | Temporal API(ES2025) | 新一代时间库 | Temporal.Now.instant() | 时间处理标准化 |
✅ 附加说明:
- ES2025 最新特性 包括:
Temporal
API(取代 Date)- 模式匹配(Pattern Matching)
- Records & Tuples(不可变数据结构)
- 增强型装饰器(Decorators Stage 3)
- Pipeline Operator(
|>
)