ES6「经典JS时代之前的语法
ES6 之前(即 ES5.1 及更早,1997--2011) 的 JS 语法与特性。这段统称为「经典 JS / ES5 时代」,是 ES6 出现前所有浏览器原生支持的基础。
时间线一句话:ES1(1997) → ES2(1998) → ES3(1999,大版本) → ES4(废弃) → ES5(2009) → ES5.1(2011) → ES6(2015)。
一、变量与函数声明
-
var(函数作用域、变量提升 hoisting、可重复声明)javascriptvar x = 1; -
函数声明
function f() { }(整体提升) -
函数表达式
var f = function() { } -
隐式全局变量(不声明直接赋值 → 泄漏到全局)
-
没有
let/const(那是 ES6)
二、原始类型与字面量
- 五种原始类型:
undefined/null/boolean/number/string(无Symbol、无BigInt) number即 IEEE-754 双精度;NaN、Infinity、-Infinity- 字面量:十进制、
0x十六进制;遗留八进制010(仅非严格模式,已废弃) - 字符串字面量
'...'/"..."(无模板字符串) - 没有
0b/0o字面量(ES6)
三、对象与原型
- 对象字面量
{ key: value },属性访问.与[] - 访问器(getter/setter)
{ get x(){}, set x(v){} }---(ES5) - 方法定义只能写
m: function(){}(无方法简写、无计算属性名) - 基于原型的继承:
prototype、constructor、new this动态绑定(四种规则:默认 /new/ 隐式 / 显式call·apply)Object内置:Object.create(ES5)、Object.defineProperty/defineProperties(ES5)Object.getOwnPropertyDescriptor/getPrototypeOf(ES5)Object.keys(ES5)、Object.freeze/seal/preventExtensions/isFrozen...(ES5)Object.prototype:hasOwnProperty、toString、valueOf、isPrototypeOf、propertyIsEnumerable
四、函数特性
-
arguments类数组对象(无剩余参数) -
call/apply(ES3)、bind(ES5,固定this) -
闭包(lexical scope)
-
IIFE 立即执行函数表达式(模块隔离的惯用法)
javascript( function(){ var private = 1; /* xxx */ })(); -
回调函数、
this丢失需var self = this或bind保存(无箭头函数) -
递归、命名函数表达式
-
没有默认参数、剩余参数、展开运算符(均 ES6)
五、控制流
if / else、switch / case / break / defaultfor(C 风格)、while/do...whilefor...in(遍历对象可枚举属性,含继承链,(ES1);无for...of)try / catch(e) / finally(catch 必须带参数,省略参数是 ES2019 才允许)throw、三元? :、逗号运算符、break/continue(含label:标签语句)
六、运算符与比较
- 算术
+ - * / %(无**,那是 ES2016)、++--、一元+/- - 位运算
& | ^ ~ << >> >>> - 赋值
=及复合+= -=等 - 关系
> < >= <=、in、instanceof - 逻辑
&& || ! - 相等:
==/!=(宽松、会发生类型转换)、===/!==(严格) typeof、void、delete、new、()分组- 没有
?./??(ES2020)
七、数组
- 数组字面量
[1,2,3]、new Array()、稀疏数组 - ES3 方法 :
push/pop/shift/unshift/slice/splice/concat/join/sort/reverse (ES5):forEach / map / filter / reduce / reduceRight / some / every、indexOf / lastIndexOf、Array.isArray- 没有
from/of/find/findIndex/fill/flat/includes/at(ES6 及以后)
八、字符串
- ES3:
charAt、charCodeAt、concat、indexOf、lastIndexOf、match、replace、search、slice、split、substring、substr、toLowerCase、toUpperCase、localeCompare,以及一批 HTML 辅助方法(bold/link...) - (ES5
):trim(仅前后空白) - 没有
includes/startsWith/endsWith/repeat(ES6)、padStart/padEnd(ES2017)、replaceAll(ES2021)
九、正则
- 正则字面量
/pat/flags与new RegExp - 标志仅
g/i/m(无u/y(ES6)、s(ES2018)、d(ES2022)、v(ES2024)) - 方法:
test、exec;字符串侧match/replace/search/split - 无具名捕获组
(?<n>)、后行断言(?<=)、\p{}属性转义
十、内置对象
Math(ES1):abs/ceil/floor/round/max/min/random/pow/sqrt/sin/cos/tan/log/exp/atan/atan2...(无trunc/sign/hypot/cbrt/log2/log10/imul,均 ES6)Date(ES1)及(ES5)Date.now()Number常量:MAX_VALUE/MIN_VALUE/NaN/POSITIVE_INFINITY/NEGATIVE_INFINITY(无EPSILON/MAX_SAFE_INTEGER,ES6)- 全局:
parseInt/parseFloat、isNaN/isFinite、eval、encodeURI/decodeURI/encodeURIComponent/decodeURIComponent(ES3)、escape/unescape(已废弃) JSON.parse/JSON.stringify---(ES5)- 错误类型:
Error/EvalError/RangeError/ReferenceError/SyntaxError/TypeError/URIError(无AggregateError(ES2021)、无Error.cause(ES2022))
十一、严格模式与遗留语法
"use strict";指令 ---(ES5)(启用更严格的校验,且禁止with与遗留八进制)with (obj) {}语句 --- 遗留语法,严格模式下报错(不推荐使用)debugger;语句- 模块系统:原生没有
import/export,靠 IIFE / 全局命名空间,或社区方案 CommonJS、AMD
小结:回到 ES5 会失去的关键能力
| 你习惯的现代写法 | ES5 替代表达 |
|---|---|
let / const |
var + 函数作用域 / IIFE |
| 箭头函数 | function(){} + var self=this 或 .bind(this) |
| 模板字符串 | 字符串拼接 '+a+' |
| 解构 / 默认 / 剩余 / 展开 | 手动赋值、arguments、循环合并 |
class |
构造函数 + 原型赋值 |
Promise / async |
回调 / 手动 Promise 垫片 |
Map / Set |
普通对象 / 数组 + indexOf |
for...of |
for + 索引 或 for...in + hasOwnProperty 过滤 |
模块 import/export |
IIFE / CommonJS / AMD |
?. / ?? |
&& 链 / ` |
简单说:ES5 时代没有块级作用域、没有 class、没有 Promise/模块/解构/箭头函数,异步全靠回调,this 需要手动绑定**。** 这些正是 ES6 一次性补齐、并让 JS 从「能用的脚本语言」变成「可工程化的语言」的核心。
ES2015(ES6)--- 奠基大版本
〇、大纲
let/const块级声明- 箭头函数
=> - 模板字符串
...${} - 解构赋值(数组 / 对象)
- 默认参数、剩余参数
...args、展开运算符... - 对象字面量增强(属性简写 / 计算属性名)
class类与继承- 模块
import/export Symbol原始类型Promise- 迭代器 +
for...of - 生成器
function*/yield Map/Set/WeakMap/WeakSetProxy/Reflect- 新 API:
Array.from/of/find/fill,Object.assign/is,Number.*,Math.*;0b/0o字面量;正则u/y
这是 JS 历史上最大的一次单版本更新,之后的 ES2016/2017... 都是在它基础上的增量。
说明:严格意义上的「ES6 = ES2015」。有些人把一切现代 JS 都叫「ES6」,
async/await、Object.values、?.、??等其实属于 ES2017 / ES2020。
一、变量声明:let / const
let:块级作用域变量,存在暂时性死区(声明前访问报错),不允许重复声明。const:声明常量(绑定不可重新赋值,但对象/数组内部可改)。
javascript
let x = 1;
const PI = 3.14;
if (true) { let y = 2; } // y 在块外不可见
二、函数增强
| 特性 | 说明 |
|---|---|
箭头函数 => |
不绑定自己的 this/arguments,继承外层;适合回调 |
| 默认参数 | function f(a = 1, b = 2){} |
| 剩余参数 Rest | function f(...args){} 收集为真正数组 |
| 展开运算符 | [...a, ...b]、Math.max(...nums) |
| 块级函数声明 | 块内声明的函数仅在块内可见 |
javascript
const add = (a, b) => a + b;
const nums = [1, 2, 3];
const merged = [...nums, 4]; // [1,2,3,4]
三、模板字符串(Template Literals)
- 反引号 ````` 包裹,支持
${}插值和多行。 - 衍生:标签模板 ``tag`...```(用于 i18n、安全转义等)。
javascript
const name = 'Tom';
const msg = `Hello ${name}, sum=${1 + 1}`;
四、解构赋值(Destructuring)
- 数组解构、对象解构、嵌套解构、重命名、默认值、参数解构。
javascript
const [a, b] = [1, 2];
const { name, age: a2 = 18 } = user; // 重命名+默认值
const [, , third] = arr; // 跳过
function f({ id, type = 'x' }) {} // 参数解构
五、对象字面量增强
- 属性简写、方法简写、计算属性名、
__proto__设置。
javascript
const x = 1;
const o = {
x, // 等同于 x: x
say() {}, // 方法简写
['key' + 1]: 100, // 计算属性名 → key1
};
六、类 class
- 语法糖,本质仍是原型继承;支持
constructor、extends、super、 静态方法static、getter/setter。
javascript
class Animal {
constructor(name) { this.name = name; }
speak() { return `${this.name} makes sound`; }
}
class Dog extends Animal {
speak() { return `${this.name} barks`; }
}
七、模块 import / export
- 真正的静态模块系统(区别于 CommonJS 的运行时加载)。
javascript
export const x = 1;
export default function() {}
import { x } from './mod.js';
import def, { x } from './mod.js';
八、Promise
- 异步编程的一等公民,解决回调地狱。
javascript
new Promise((resolve, reject) => {
/* ... */
}).then(r => {
/* ... */
}
).catch(e => {
/* ... */
});
九、迭代器与 for...of
- 任何实现了
[Symbol.iterator]的对象都可被for...of遍历(Array、Set、Map、String、arguments、NodeList...)。
javascript
for (const v of arr) {
/* ... */
}
十、生成器 Generator
function*+yield,可暂停/恢复执行;也是异步流程(co 库)和迭代器工厂的基础。
javascript
function* gen() {
yield 1; yield 2;
}
const g = gen(); g.next(); // {value:1, done:false}
十一、Symbol
- 新增的第七种原始类型,用作唯一键值,避免属性名冲突;内置了许多 well-known symbols(
Symbol.iterator、Symbol.toStringTag等)。
javascript
const key = Symbol('desc');
const obj = { [key]: 'hidden' };
十二、新数据结构
Map(键值对任意类型)、Set(去重)、WeakMap/WeakSet(弱引用,键只能是对象,不可遍历)。
javascript
const m = new Map();
m.set(obj, 1);
m.get(obj);
const s = new Set([1, 1, 2]);
// {1, 2}
十三、Proxy 与 Reflect
Proxy:拦截/自定义对象的基础操作(get/set/apply/construct...)。Reflect:与 Proxy 钩子一一对应的静态方法集合,规范了对对象的内省操作。
javascript
const p = new Proxy(target, {
get(t, k) {
return k in t ? t[k] : 'default';
}
});
十四、内置对象新增方法(ES6 引入)
- Array :
Array.from、Array.of、find、findIndex、fill、copyWithin、keys、values、entries - String :
includes、startsWith、endsWith、repeat、codePointAt、normalize、String.fromCodePoint - Number :
Number.isFinite、Number.isNaN、Number.isInteger、Number.parseInt、Number.parseFloat、Number.EPSILON、Number.MAX_SAFE_INTEGER、Number.MIN_SAFE_INTEGER - Math :
Math.sign、Math.trunc、Math.cbrt、Math.hypot、Math.log2、Math.log10、Math.imul、Math.clz32、Math.expm1、Math.log1p、Math.cosh... 双曲函数族 - Object :
Object.assign、Object.is、Object.setPrototypeOf、Object.getPrototypeOf、Object.getOwnPropertySymbols、Object.preventExtensions等规范化
javascript
[1, 2, 3].find(n => n > 1); // 2
'hello'.includes('ell'); // true
Object.assign({}, a, b); // 浅合并
十五、字面量语法扩展
- 二进制
0b101与八进制0o17字面量(旧八进制010已废弃)。
十六、正则表达式增强
u标志(Unicode 模式,正确处理码点)、y标志(粘连 sticky)、实例.flags属性、RegExp.prototype.unicode/sticky。
十七、其它机制
- 尾调用优化(TCO):严格模式下尾递归不新增栈帧(仅少数引擎实现)。
new.target:检测函数是否通过new调用。- 函数名推导 :匿名函数表达式会推断
name。
ES2016(ES7)
-
求幂运算符
**与**=(语法)javascript2 ** 3; // 8 x **= 2; -
Array.prototype.includes(含NaN判断)
ES2017(ES8)
-
async/await(语法)javascriptasync function f() { const r = await fetch(url); } -
函数参数与调用允许多余的尾随逗号 (语法)
javascriptfunction g(a, b,) { } -
Object.values/Object.entries/Object.getOwnPropertyDescriptors -
字符串填充
padStart/padEnd -
SharedArrayBuffer与Atomics
ES2018(ES9)
-
异步迭代 :
for await...of与异步生成器async function*(语法)javascriptfor await (const x of asyncIterable) {} -
对象 rest / spread (语法)
javascriptconst { a, ...rest } = obj; const c = { ...a, ...b }; -
Promise.prototype.finally -
正则增强(语法):具名捕获组
(?<name>)、后行断言(?<=)、点匹配所有s(dotAll)标志、Unicode 属性转义\p{...}javascriptconst { groups: { year } } = /(?<year>\d{4})/.exec(s);
ES2019(ES10)
-
数组
flat/flatMap -
Object.fromEntries(与entries互逆) -
字符串
trimStart/trimEnd -
可选 catch 绑定 :
catch {}可省略参数(语法)javascripttry { /* ... */ } catch { /* 不需要 e */ } -
Symbol.prototype.description -
JSON 超集(允许行分隔符 U+2028/2029)与
JSON.stringify保形输出
ES2020(ES11)
-
可选链
?.(语法)javascriptuser?.address?.city; -
空值合并
??(语法,只在null/undefined时生效)javascriptconst v = input ?? 'default'; -
BigInt与字面量123n(语法) -
动态
import()(语法,返回 Promise) -
globalThis、import.meta -
export * as ns from '...'(聚合导出,语法) -
Promise.allSettled、String.prototype.matchAll
ES2021(ES12)
-
逻辑赋值运算符
&&=/||=/??=(语法)javascriptobj.x ??= defaultValue; -
数字分隔符
1_000_000(语法,仅可读性) -
String.prototype.replaceAll -
Promise.any(任意一个成功即 resolve) -
WeakRef与FinalizationRegistry -
Array.prototype.sort改为稳定排序
ES2022(ES13)
-
顶层
await(模块顶层可直接await,语法) -
类字段 全面落地(语法):
- 公共实例字段、私有字段
#x、私有方法#m() - 静态字段 / 静态私有成员
- 静态初始化块
static {}
javascriptclass C { #secret = 1; static #cnt = 0; static { this.init(); } #helper() {} } - 公共实例字段、私有字段
-
索引方法
.at()(Array / String / TypedArray,支持负索引-1) -
Object.hasOwn(替代hasOwnProperty.call) -
Error.prototype.cause(错误链路) -
正则匹配索引
d标志
ES2023(ES14)
-
Array.prototype.findLast/findLastIndex -
不改原数组的数组副本方法 (语法/API):
toSorted、toReversed、toSpliced、withjavascriptconst sorted = arr.toSorted((a, b) => a - b); // 原数组不变 const replaced = arr.with(0, 99); -
脚本文件头 Hashbang
#!/usr/bin/env node语法合法化 -
TypedArray对应的findLast/with/toSorted等副本方法
ES2024(ES15,最新)
-
Array.fromAsync(异步可迭代 → 数组) -
Set 集合运算方法 (语法/API):
union、intersection、difference、symmetricDifference、isSubsetOf、isSupersetOf、isDisjointFrom -
分组方法 :
Object.groupBy(返回对象)、Map.groupBy(返回 Map)javascriptconst byAge = Object.groupBy(users, u => u.age > 18 ? 'adult' : 'minor'); -
Promise.withResolvers(直接拿到resolve/reject) -
正则
v标志(unicodeSets,增强字符类集合运算) -
ArrayBuffer.prototype.resize/transfer、SharedArrayBuffer的transfer(缓冲区可转移/扩容)
速查:哪些是"语法"、哪些是"API"
| 类别 | 典型例子 |
|---|---|
| 纯语法(写法变化) | let/const、=>**、?.、??、模板字符串、解构、class 字段/#、rest/spread、async/await、for await、动态 import()`、数字分隔符、逻辑赋值、尾随逗号、可选 catch |
| 内置 API | Promise.*、Array.includes/findLast/flat/toSorted、Object.entries/groupBy、Set 集合方法、BigInt、WeakRef、Reflect、globalThis |
建议记忆锚点:ES6 打地基,ES2017 给 async,ES2020 给
?./??,ES2022 给类字段与顶层 await,ES2024 给 Set 集合运算与 groupBy。