最近在面试中,面试官问我知道有哪些es6的新特性?我总觉得自己记得很多,但一回答只答出来少数,let,const,promise,Symbol然后就卡壳了,还是面试官提醒我我才挤出几个,面试官说箭头函数,解构赋值,我回答,对对对,还有模块化,模板字符串, 今天这篇文章,我们将把es6新特性给大家一一罗列出来,看下有哪些是平时记得但面试遗忘了的。帮助你在面试和日常开发中更加熟练地运用它们。
1. let 与 const:块级作用域变量声明
这个知识点可以参考以下文章
JavaScript变量声明:var、let、const的底层机制与最佳实践JavaScript变量声明:var、let - 掘金
1.1 语法
javascript
let 变量名 [= 初始值];
const 常量名 = 值; // 声明时必须初始化
1.2 作用域规则
- 词法作用域 + 块级 :
let
和const
的作用域仅限于花括号{}
内。 - 无声明提升 :在
let
和const
声明之前访问变量会抛出ReferenceError
。 - 禁止重复声明:同一作用域内不能重复声明同名变量。
1.3 const 的「只读」含义
- 绑定只读 :
const
声明的变量不能重新赋值,但对象或数组的内部属性可以改变。 - 真正不可变 :若需要完全不可变的对象,需配合
Object.freeze()
或使用 Immutable.js。
1.4 循环中的闭包陷阱
javascript
// ❌ 旧 var 写法
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0); // 3 3 3
}
// ✅ let 每次迭代生成新绑定
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0); // 0 1 2
}
1.5 性能/工程化
- 性能 :在现代引擎(如V8)中,
let
和const
与var
性能几乎无差别。 - 最佳实践 :默认使用
const
,仅当需要重新赋值时使用let
,彻底淘汰var
。
2. 箭头函数 Arrow Functions
这个知识点可以参考以下文章
面试官问箭头函数和普通函数的区别?这才是面试官最想听到的在 JavaScript 开发中,this 的指向问题一直是困扰 - 掘金
2.1 语法速查
javascript
() => expression
param => expression
(p1, p2) => { statements; return val; }
2.2 核心特性
- 词法作用域 this :箭头函数继承外层函数或全局的
this
,不再受调用方式影响。 - 无自己的
arguments
、super
、new.target
。 - 不可用作构造函数 :
new (() => {})
会抛出TypeError
。 - 无
prototype
属性。
2.3 常见坑
- 对象字面量中的箭头函数 :
this
不会指向该对象。
javascript
const obj = {
name: 'Tom',
say: () => console.log(this.name) // this 指向外层,一般 window -> undefined
};
- 返回字面量对象时需加括号:
javascript
const makeUser = (name, age) => ({ name, age }); // 若去掉 () 会被解析为函数体
2.4 性能
- 性能差异:在 V8 中箭头函数与普通函数性能差异 <1%,可读性优先。
3. 模板字符串 Template Literals
3.1 语法
使用反引号 `````,支持多行字符串与 ${expression}
插值。
3.2 标签模板 Tagged Templates
javascript
function highlight(strings, ...values) {
return strings.reduce((s, str, i) =>
s + str + (values[i] ? `<b>${values[i]}</b>` : ''), '');
}
const name = 'Tom', age = 20;
console.log(highlight`Name: ${name}, Age: ${age}`);
3.3 转义规则
- 反引号需写成
\`
。 ${
需写成\${
。- 所有空白字符(包括换行与缩进)都会被保留,格式化需自行处理。
3.4 性能
- 编译阶段:在编译阶段会被拆成字符串数组 + 表达式数组,运行时拼接,无额外开销。
4. 解构赋值 Destructuring
4.1 数组解构
javascript
const [a, , c, ...rest] = [1, 2, 3, 4, 5];
// a=1, c=3, rest=[4,5]
4.2 对象解构
javascript
const { x, y: newY = 0 } = { x: 10 };
// x=10, newY=0
4.3 默认值触发条件
仅当对应属性严格等于 undefined
时才会使用默认值。
4.4 嵌套 / 重命名 / 剩余
javascript
const { user: { name }, meta: { created } = {} } = response;
const { a, b, ...others } = obj; // others 包含剩余可枚举属性
4.5 函数参数解构
javascript
function ajax({ url, method = 'GET', timeout = 5000 } = {}) {
...
}
4.6 常见坑
- 数组解构对"可迭代对象"有效,非数组需先转为迭代器。
- 对象解构依赖属性枚举顺序。
5. 类 class、extends、super
5.1 语法糖本质
仍是原型继承的语法包装,但隐藏了 .prototype
、Object.create
等底层细节。
5.2 声明 vs 表达式
javascript
class Foo {} // 声明,不可提升
const Bar = class {}; // 表达式
5.3 成员速查
- 实例属性 :写在
constructor
里this.x = 1;
- 实例方法:直接写方法名
- 静态方法/属性 :
static method() {}
- 私有字段 (Stage 3,ES2022 定稿):
#count = 0;
5.4 super 用法
super()
:在constructor
中调用父类构造函数。super.method()
:调用父类原型方法。
5.5 继承内建构造函数
javascript
class MyArray extends Array {
first() { return this[0]; }
}
6. Promise 与异步流程
6.1 Promise 状态机
- 三种状态:
pending
→fulfilled
/rejected
,只能转换一次。
6.2 静态方法
Promise.resolve(value)
Promise.reject(reason)
Promise.all(iterable)
Promise.race(iterable)
Promise.allSettled(iterable)
(ES2020)
下面是我对这章内容所做的一篇总结,大家可以参考下 深入理解 Promise 并行处理:从 Promise.all 到 allSettled
6.3 链式调用注意
- 每个
.then()
返回的新Promise
由回调返回值决定。 - 若返回
Promise
会"解包";若抛出错误则链进入 rejection。
6.4 与 async/await 的关系
async/await
只是Promise
的语法糖,ES2017 引入。- 用
try/catch
捕获async
函数内抛出的错误,相当于.catch()
。
7. 模块化 Module(import / export)
7.1 导出方式
- 命名导出 :
export const a = 1;
- 默认导出 :
export default something;
- 聚合导出 :
export * from './util.js';
7.2 导入方式
- 命名导入 :
import { a, b as bee } from './mod.js';
- 默认导入 :
import React from 'react';
- 混合导入 :
import React, { useState } from 'react';
- 动态导入 :
const mod = await import('./lazy.js');
7.3 运行时行为
- 静态分析:ES Module 是静态分析,编译时确定依赖关系,支持 Tree Shaking。
- 浏览器支持 :需
<script type="module">
,自动延迟执行、严格模式、跨域 CORS。 - Node.js 支持 :
.mjs
或"type":"module"
,与 CommonJS 交互有差异(require
不支持顶层await
)。
7.4 循环依赖
- ES Module 通过"绑定"而非"值拷贝"解决循环引用:
javascript
// a.js
import { foo } from './b.js';
export const bar = foo + 1;
// b.js
import { bar } from './a.js';
export const foo = bar ? bar - 1 : 0;
8. 新增数据结构
这篇文章可供参考: 深入探索 ES6 中的 Map 数据结构在 JavaScript 的发展历程中,ES6(ECMAScript 2015 - 掘金
8.1 Map
- 任意类型键,保持插入顺序。
- 方法 :
set/get/has/delete/clear/size
,以及迭代器keys/values/entries/forEach
。 - 与 Object 区别:键不会强制转字符串、可迭代、size 属性、更好性能(频繁增删场景)。
8.2 WeakMap / WeakSet
- 键必须是对象,不计入 GC 引用计数;不可枚举、无 size。
- 常用于缓存、元数据。
8.3 Set / WeakSet
- 唯一值集合,API 类似 Map。
- 快速去重 :
[...new Set(arr)]
。
9. 数组 & 对象扩展
9.1 Array 扩展
Array.from(arrayLike, mapFn, thisArg)
:把类数组/可迭代对象转为真数组,可替代[].slice.call(arguments)
。Array.of(...items)
:避免new Array(3)
创建稀疏数组。find(predicate)
/findIndex
/includes(value)
/fill
/copyWithin
/keys
/values
/entries
。
9.2 Object 扩展
- 属性简写 :
{ x, y() {} }
- 计算属性名 :
{ ['id_' + i]: value }
Object.assign(target, ...sources)
:浅拷贝合并。Object.is(a, b)
:类似===
,但Object.is(NaN, NaN) === true
,-0 !== 0
。Object.keys/values/entries
返回可枚举自有属性。
9.3 扩展运算符 ...
- 数组/对象浅拷贝、合并、函数剩余参数、解构剩余项。
- 对象展开仅在 Stage 4(ES2018)纳入标准 ,Babel 需
@babel/plugin-proposal-object-rest-spread
。
10. Symbol 与内置 Symbol
10.1 基本用法
javascript
const sym = Symbol('desc');
const obj = { [sym]: 123 };
10.2 内置 Symbol
Symbol.iterator
:定义默认迭代器(for...of 使用)。Symbol.toStringTag
:影响Object.prototype.toString.call(obj)
。Symbol.asyncIterator
:配合异步迭代器(for await...of)。Symbol.hasInstance
、Symbol.match
、Symbol.replace
等用于自定义语言内部算法。
11. 迭代器 & 生成器
11.1 可迭代协议
任何对象只要实现 @@iterator
(即 [Symbol.iterator]()
返回迭代器对象)即可被 for...of 遍历。
11.2 生成器函数
javascript
function* gen() {
yield 1;
yield* anotherGen(); // 委托
return 'done';
}
const g = gen();
g.next(); // {value: 1, done: false}
11.3 高级用法
- 生成器 + Promise → 协程(co 库、Redux-saga)。
- 生成器返回的迭代器也是可迭代对象 ,因此可
for (const v of gen()) {}
。
12. 函数参数增强
12.1 默认值
javascript
function f(a, b = a + 1) {} // 默认表达式可引用前面参数
12.2 剩余参数
javascript
function sum(...nums) { return nums.reduce((s, n) => s + n, 0); }
- 剩余参数是真正的 Array ,无需
arguments
。 - 必须在形参列表最后,且每个函数只能有一个。
12.3 展开参数
javascript
Math.max(...[1, 2, 3]);
13. Proxy 与 Reflect(ES6 元编程)
13.1 Proxy
- 在目标对象前架设拦截层,重定义基本操作(get、set、has、construct...)。
- 常用于数据劫持、验证、日志、Revocable Proxy。
javascript
const proxy = new Proxy(target, {
get(t, key, receiver) {
console.log('access', key);
return Reflect.get(t, key, receiver);
}
});
13.2 Reflect
- 把语言内部方法(如 [[Get]]、[[Set]])暴露为函数,统一返回值与异常。
- 与 Proxy 搭配 ,避免 this 绑定问题:
Reflect.set(target, key, value, receiver)
。
14. 二进制 & 八进制字面量、Unicode 增强
- 二进制
0b1010
,八进制0o777
(老写法0777
已废弃)。 - Unicode 码点转义
\u{1F4A9}
(> 0xFFFF)。 String.fromCodePoint / codePointAt
处理 4 字节字符。
15. 工程化 & 兼容性
15.1 转译
- Babel:preset-env 根据目标浏览器自动转译。
- TypeScript:本身就是 ES6+ 的超集,编译到目标 ES 版本。
15.2 Polyfill
core-js
:按需注入 Map、Promise、Array.prototype.includes 等。- 动态 Polyfill 服务:polyfill.io。
15.3 Lint / 规范
- ESLint + eslint-plugin-import + eslint-plugin-promise。
- Airbnb、Standard、Google 规范均要求优先 const、箭头函数、模板字符串。
15.4 性能监控
- 通过 Lighthouse、Webpack Bundle Analyzer 观察转译后包体;箭头函数、class 字段会被降级,体积可能增大。
16. 速查表(常见场景写法)
- 深拷贝简单对象 :
const clone = JSON.parse(JSON.stringify(obj));
(注意函数、循环引用)。 - 优雅 sleep :
const sleep = ms => new Promise(r => setTimeout(r, ms));
- 过滤唯一 :
const unique = arr => [...new Set(arr)];
- 对象合并 :
const merged = { ...a, ...b };
- 可选链/空值合并 (ES2020,但常与 ES6 项目一起使用):
user?.profile?.avatar ?? 'default.png'
结语
ES6 并非终点,ES2016-ES2023 陆续补充了 async/await
、**
幂运算、类字段、私有方法、顶层 await、Array.prototype.at、正则命名组等特性。建议以「ES6 为基础,逐步补充后续提案」进行团队技术栈升级。
希望这篇文章能帮助你在面试中更加自信地回答关于ES6新特性的问题,并在日常开发中更加高效地运用这些特性。如果你有任何疑问或补充,欢迎在评论区留言。