前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版

ES6 系统复习 ES2015 ES2016 ES2017 ES2018 ES2019 特性全梳理

首页2019-11-17 19:50:43Front-End
JavaScriptES6ES2015前端面试

ES6 全版本特性知识图谱封面

面试前翻 ES6,最容易踩的坑不是「不会写」,而是记混了年份和归属。有人把 Object.values() 说成 ES6 新增,有人以为 includes() 是数组和字符串一起加的,还有人把 async/await 归到 ES2015 里去。这些细节平时不影响写代码,被追问一句「这个是哪一版进的标准」就容易卡壳。

这篇是我按年份重新捋的一份复习笔记,从 ES2015 一路排到 ES2019,外加当年还在提案阶段的一批语法。每一节不只列 API 名字,还会补上它在解决什么问题、什么场景真用得上、边界条件在哪。读完你至少能把「ES6 到底包含哪些东西」这件事讲清楚,面试被追问细节时心里有底。

在本篇文章中,我们将从浅入深,和大家一起学习以下知识:

  • ES6 和 ES2015 到底是什么关系,为什么不该再叫 ES7、ES8
  • ES2015 的全量特性,声明、解构、字符串、数值、对象、数组、函数、正则、Symbol、Set/Map、Proxy/Reflect、Class、Module、Iterator、Promise、Generator
  • ES2016 到 ES2019 这四年每年加了什么,为什么后面几年的更新越来越小
  • 当年还在提案里的 ?.、??、BigInt、私有属性、顶层 await,现在都跑到哪一步了
  • 每个特性的重点难点和踩坑清单,可以直接当面试自查表用

# 一、前言

  • ES6是ECMA为JavaScript制定的第6个标准版本
  • 标准委员会最终决定,标准在每年6月正式发布并作为当年的正式版本,接下来的时间里就在此版本的基础上进行改动,直到下一年6月草案就自然变成新一年的版本,这样一来就无需以前的版本号,只要用年份标记即可。ECMAscript 2015是在2015年6月发布ES6的第一个版本。以此类推,ECMAscript 2016是ES6的第二个版本、 ECMAscript 2017是ES6的第三个版本。ES6既是一个历史名词也是一个泛指,含义是5.1版本以后的JavaScript下一代标准,目前涵盖了ES2015、ES2016、ES2017、ES2018、ES2019

所以有些文章上提到的ES7(实质上是ES2016)、ES8(实质上是ES2017)、ES9(实质上是ES2018)、ES10(实质上是ES2019),实质上都是一些不规范的概念。从ES1到ES6,每个标准都是花了好几年甚至十多年才制定下来,你一个ES6到ES7,ES7到ES8,才用了一年,按照这样的定义下去,那不是很快就ES20了。用正确的概念来说ES6目前涵盖了ES2015、ES2016、ES2017、ES2018、ES2019

这里补一句我自己的理解。年份命名不只是换个叫法,它背后是 TC39 把「攒大版本」改成了「小步快跑」。一个提案只要走完 Stage 0 到 Stage 4 五个阶段,就直接搭上最近一班年度快车,不用等整个大版本谈拢。所以你会看到 ES2015 一口气塞了几十个特性,后面几年每年只有三五条,这不是标准停滞了,恰恰是流程顺了。

下面这张图是版本演进的整体脉络,可以先扫一眼建立坐标系,后面每一节都能对回这张图上。

ECMAScript 各版本发布时间线与命名规则

顺着上面聊,日常交流里说「ES6」通常泛指 ES5.1 之后的一整套新语法,说「ES2015」才是精确指某一年的标准。写简历和答面试题的时候建议用年份,不容易被挑刺。

# 二、ES2015

ES2015 是这套标准里最厚的一版,也是绝大多数人口中「ES6」真正指的那一版。它一次性补齐了块级作用域、模块系统、类语法、迭代协议、异步原语这几块 JavaScript 缺了十几年的地基。后面 ES2016 到 ES2019 加的东西,基本都是在这批地基上打补丁。

所以这一节篇幅最长,建议按图里的分类逐块过。

ES2015 特性全景分类图

# 声明

先看这块。var 最让人头疼的地方有两个,一是没有块级作用域,for 循环里声明的变量会漏到外面;二是变量提升,声明还没执行就能访问到 undefined。let 和 const 就是冲着这两个问题来的。

  • const命令:声明常量
  • let命令:声明变量

作用

作用域

  • 全局作用域
  • 函数作用域:function() {}
  • 块级作用域:{}

作用范围

  • var命令在全局代码中执行
  • const命令和let命令只能在代码块中执行

赋值使用

  • const命令声明常量后必须立马赋值
  • let命令声明变量后可立马赋值或使用时赋值

声明方法:var、const、let、function、class、import

重点难点

  • 不允许重复声明
  • 未定义就使用会报错:const命令和let命令不存在变量提升
  • 暂时性死区:在代码块内使用let命令声明变量之前,该变量都不可用

暂时性死区这块很多人记成了「let 没有提升」。严格说变量还是被提升到了块顶部,只是在执行到声明语句之前它处于未初始化状态,访问就抛 ReferenceError。这个区别在面试里会被追问,答「没有提升」容易被反问一句「那为什么 typeof 也报错」。

再补一个 const 的老误会。const 锁的是绑定不是值,const arr = [] 之后 arr.push(1) 完全合法,只有 arr = [] 才报错。想让对象内容也不可改,得配合 Object.freeze(),而且它只冻一层。

# 解构赋值

解构解决的是「从一坨数据里挑几个字段出来」这件事。以前得写 const name = res.data.user.name 一行一行摘,现在一行搞定,函数入参也能顺手带默认值。这套语法在处理接口返回和写工具函数时使用频率极高。

  • 字符串解构:const [a, b, c, d, e] = "hello"
  • 数值解构:const { toString: s } = 123
  • 布尔值解构:const { toString: b } = true

对象解构

  • 形式:const { x, y } = { x: 1, y: 2 }
  • 默认:const { x, y = 2 } = { x: 1 }
  • 改名:const { x, y: z } = { x: 1, y: 2 }

数组解构

  • 规则:数据结构具有Iterator接口可采用数组形式的解构赋值
  • 形式:const [x, y] = [1, 2]
  • 默认:const [x, y = 2] = [1]

函数参数解构

  • 数组解构:function Func([x = 0, y = 1]) {}
  • 对象解构:function Func({ x = 0, y = 1 } = {}) {}

应用场景

  • 交换变量值:[x, y] = [y, x]
  • 返回函数多个值:const [x, y, z] = Func()
  • 定义函数参数:Func([1, 2])
  • 提取JSON数据:const { name, version } = packageJson
  • 定义函数参数默认值:function Func({ x = 1, y = 2 } = {}) {}
  • 遍历Map结构:for (let [k, v] of Map) {}
  • 输入模块指定属性和方法:const { readFile, writeFile } = require("fs")

重点难点

  • 匹配模式:只要等号两边的模式相同,左边的变量就会被赋予对应的值
  • 解构赋值规则:只要等号右边的值不是对象或数组,就先将其转为对象
  • 解构默认值生效条件:属性值严格等于undefined
  • 解构遵循匹配模式
  • 解构不成功时变量的值等于undefined
  • undefined和null无法转为对象,因此无法进行解构

第三条那个「严格等于 undefined」是真踩过的坑。接口返回 { count: null },你写 const { count = 0 } = res,拿到的还是 null 不是 0,因为默认值只在属性值严格等于 undefined 时才生效。后来 ES2020 补的 ?? 就是专门收拾 null 这种情况的,这个后面提案那一节还会说。

还有个写法值得单拎出来:function Func({ x = 1, y = 2 } = {}) 里那个外层 = {} 千万别省。省了之后调用 Func() 不传参,解构 undefined 直接报错。

# 字符串扩展

字符串这块的改动可以分两拨看。一拨是模板字符串和标签模板,解决拼接可读性;另一拨是一堆 Unicode 相关方法,解决 JavaScript 早年只按 16 位处理字符、遇到 emoji 和生僻字就算错长度的老问题。

  • Unicode表示法:大括号包含表示Unicode字符(\u{0xXX}或\u{0XXX})
  • 字符串遍历:可通过for-of遍历字符串
  • 字符串模板:可单行可多行可插入变量的增强版字符串
  • 标签模板:函数参数的特殊调用
  • String.raw():返回把字符串所有变量替换且对斜杠进行转义的结果
  • String.fromCodePoint():返回码点对应字符
  • codePointAt():返回字符对应码点(String.fromCodePoint()的逆操作)
  • normalize():把字符的不同表示方法统一为同样形式,返回新字符串(Unicode正规化)
  • repeat():把字符串重复n次,返回新字符串
  • matchAll():返回正则表达式在字符串的所有匹配
  • includes():是否存在指定字符串
  • startsWith():是否存在字符串头部指定字符串
  • endsWith():是否存在字符串尾部指定字符串

重点难点

以上扩展方法均可作用于由4个字节储存的Unicode字符上

这句是整节的关键。"👍".length 返回 2 而不是 1,因为它由两个代理对码元组成;用 for-of 遍历或者 [..."👍"] 展开,拿到的才是一个完整字符。做输入框字数统计、做昵称截断的时候,这个差别直接决定了会不会把 emoji 劈成两半变乱码。这个我踩过,当时截出来的半个字符在 iOS 上显示成方块。

再纠正一处归属。上面列表里的 matchAll() 严格说不属于 ES2015,它是后来才进标准的方法,很多教材按主题把它并到「字符串扩展」一章里,容易让人以为是同一批。具体进标准的年份以 MDN 为准,面试答「后来补的」比乱报年份安全。

# 数值扩展

数值这块新增的东西多,但日常真正高频的就三四个。二进制和八进制字面量是给位运算和权限掩码用的;Number.isNaN() 和 Number.isInteger() 是为了绕开全局 isNaN() 会先做类型转换的坑;Number.EPSILON 则是浮点数比较的标准解法。

fe
  • 一、前言
  • 二、ES2015
    • 声明
    • 解构赋值
    • 字符串扩展
    • 数值扩展
    • 对象扩展
    • 数组扩展
    • 函数扩展
    • 正则扩展
    • Symbol
    • Set
    • Map
    • Proxy
    • Reflect
    • Class
    • Module
    • Iterator
    • Promise
    • Generator
  • 三、ES2016
    • 数值扩展
    • 数组扩展
  • 四、ES2017
    • 字符串扩展
    • 函数扩展
  • 五、ES2018
    • 字符串扩展
    • 正则扩展
    • Promise
    • Async
  • 六、ES2019
    • 字符串扩展
    • 对象扩展
    • 数组扩展
    • 函数扩展
    • Symbol
  • 七、ES提案
    • 声明
    • 数值扩展
    • 对象扩展
    • 函数扩展
    • Promise
    • Realm
    • Class
    • Module
    • Async
  • 总结
  • 参考

← Python基础小结(一) 从语法到标准库的入门笔记Cordova 结合 Vue 打包混合 App 从环境搭建到调用原生插件 →