跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScriptNode.js大前端

JavaScript 高级进阶 ES6 至 ES13 详解

综述由AI生成JavaScript 从 ES6 到 ES13 经历了显著的语言特性演进。详细解析了各版本核心更新,包括 ES6 的 let/const、箭头函数、模板字符串及数据结构(Set/Map);ES7 的指数运算符与 includes;ES8 的对象方法与字符串填充;ES10 的数组扁平化与参数处理;ES11 的空值合并、可选链及 globalThis;以及 ES12 和 ES13 引入的弱引用、逻辑赋值、负索引访问和类私有成员等。内容涵盖语法变化、作用域机制、内存管理及新 API 应用,旨在帮助开发者掌握现代 JavaScript 标准规范。

赛博朋克发布于 2026/2/25更新于 2026/5/2724 浏览
1. ES6 - 对象字面量增强

对象字面量的增强写法主要体现在以下几个方面,以提高代码的可读性、可维护性和功能性:

  • 属性简写:当属性名和变量名相同时,可以省略属性名,直接写变量名
  • 方法简写:可以省略 function 关键字,直接写方法名
  • 计算属性名:使用表达式的结果作为对象属性的键名

当前有多个变量,想要把它们放入到对象中,并且在对象中定义一个方法,在 ES6 之前是这样写的:

const name = 'liang'
const age = 20
const object = {
  name: name,
  age: age,
  foo: function() {}
}

属性简写和方法简写的使用示例:

const name = 'liang'
const age = 20
const object = {
  // property shorthand (属性简写)
  name, age,
  // method shorthand (方法简写)
  foo() {}
}

可以使用箭头函数作为方法,这样可以更简洁地定义函数,但是要注意箭头函数中的 this 指向。

const object = {
  foo() { console.log(this) },
  bar: () => { console.log(this) }
}

计算属性名:[] 是计算属性名的语法,使用表达式的结果作为对象属性的键名。

const name = 'liang'
const object = {
  // ES6 计算属性名,等价于 liang456
  [name + 456]() { console.log('ES6 的计算属性写法'); }
}
object[name + '123'] = function() { console.log('ES6 之前的计算属性写法'); }
object.liang123()
object.liang456()
2. ES6 - 对象和数组的解构

ES6 解构赋值是一种强大的语法特性,它允许你从数组或对象中提取数据,并将其赋值给变量。这种语法使得从复杂的数据结构中提取数据变得更加简洁和直观。

// 现有一个数组或对象,要将里面的多个值取出来
const arr = ['html', 'css', 'js']
// 在 ES6 之前,是这样获取的
const item1 = arr[0]
const item2 = arr[1]
const item3 = arr[2]
// ES6 新增解构赋值,可以这样获取
const [value1, value2, value3] = arr
// 对象的解构赋值
const { name, age } = { name: 'liang', age: 20 }
3. ES6 - let / const 的基本使用

在 ES5 中声明变量都是使用的 var 关键字,从 ES6 开始新增了两个关键字可以声明变量:let、const。

// variable 变量
var a = 1
let b = 2
// constant 常量
const c = 3

通过 let、const 声明的变量不可以重复定义。

var a = 1
var a = 1
let b = 2
// let b = 2 // Uncaught SyntaxError: Identifier 'b' has already been declared
const c = 3
// const c = 3 // Uncaught SyntaxError: Identifier 'c' has already been declared

const 本质上是传递的值不可以修改,如果传递的是引用类型,可以通过引用找到对象,去修改对象内部的属性。

// const 本质上是传递的值不可以修改
// 但是,如果传递的是一个引用类型 (内存地址),可以通过引用找到对应的对象,去修改对象内部的属性
const obj = { name: 'liang' }
obj.name = 'hello'
4. ES6 - let / const 的作用域提升

let、const 和 var 的另一个重要区别是作用域提升:

  • var 声明的变量是会进行作用域提升的,在声明之前使用该变量不会报错,只是没有值
  • 使用 let、const 声明的变量,在声明之前使用该变量会报错
console.log(a) // undefined
var a = 1
console.log(b) // Uncaught ReferenceError: Cannot access 'b' before initialization
let b = 1

暂时性死区:

  • 它表达的意思是在一个代码中,使用 let/const 声明的变量,在声明之前变量都是不可访问的
  • 我们将这种现象称之为暂时性死区
5. ES6 - let / const 和 window 的关系

Window 对象添加属性:

  • 全局通过 var 声明的变量,会被添加到 window 对象上,作为 window 对象的属性
  • let、const 是不会给 window 上添加任何属性的
var name = 'liang'
console.log(window.name) // liang
let title = 'vue'
console.log(window.title) // undefined
6. ES6 - 新增的块级作用域

在 ES5 中只有两个东西会形成作用域:全局作用域、函数作用域。

在 ES6 中新增了块级作用域,并且通过 let、const、function、class 声明的标识符是具备块级作用域限制的。

if、switch、for 语句都是块级作用域。

// if 语句的代码就是块级作用域
if (true) {
  let foo = 'foo'
}
console.log(foo) // Uncaught ReferenceError: foo is not defined

// switch 语句的代码也是块级作用域
let color = 'red'
switch (color) {
  case 'red':
    var bar = 'bar'
    let bgColor = '#000'
}
console.log(bar)
console.log(bgColor) // Uncaught ReferenceError: bgColor is not defined

// for 语句的代码也是块级作用域(这个场景用的最多,强烈推荐使用 let)
for (var i = 0; i < 5; i++) {}
console.log(i) // 5
for (let j = 0; j < 5; j++) {}
console.log(j) // Uncaught ReferenceError: j is not defined

我们来看一下 for 循环语句中,起始变量使用 var 声明的导致的问题:无论点击哪个按钮输出结果都是一样的。

const btns = document.getElementsByTagName('button')
// 特别注意:这里是 var 声明的起始变量
for (var i = 0; i < btns.length; i++) {
  btns[i].onclick = function() {
    console.log('第' + i + '个按钮被点击') // 第 3 个按钮被点击
  }
}

这是因为 var 声明的变量 i 是全局作用域,函数中没有变量 i 就会往上级作用域找,循环结束后 i 就已经变为 3。

学习过块级作用域后,只需要将 i 的声明从 var 改为 let 即可,这就是块级作用域给我们带来的好处。

// 使用 let 声明起始变量 i,使其形成块级作用域
for (let i = 0; i < btns.length; i++) {
  btns[i].onclick = function() {
    console.log('第' + i + '个按钮被点击')
  }
}
7. ES6 - 模板字符串的使用

ES6 模板字符串是一种增强型的字符串表示方式,使用反引号包裹内容,支持在字符串中嵌入变量、表达式以及多行文本,极大的简化了字符串拼接和格式化操作。

基本语法:模板字符串通过反引号定义,可以包含变量和表达式,使用 ${} 语法进行插入。

const string = `my name is ${name}, age is ${age + 5}, height is ${height}`

多行文本:模板字符串天然支持多行文本,无需使用 和字符串拼接,可以直接换行书写。

const html = `<div>
  <button>按钮</button>
  <button>按钮</button>
  <button>按钮</button>
</div>`
8. ES6 - 标签模板字符串

标签模板字符串是 ES6 中的一个高级特性,它允许你通过一个函数来处理模板字符串。

// 当使用标签模板字符串调用函数时
// 第一个参数:依然是模版字符串中的整个字符串,只是被切成了多块,放到了一个数组中
// 第二个参数:模板字符串中的第一个 ${}
// 第三个参数:模板字符串中的第二个 ${}
function foo(m, n, x) {
  console.log({ m, n, x })
}
// 标签模板字符串调用
const name = 'liang'
const age = 18
foo`hello${name}world${age}!`
9. ES6 - 函数参数的默认值

在 ES6 中,函数参数的默认值功能极大的简化了函数定义和调用过程。

// ES6 可以给函数的参数设置默认值
function foo(m = '默认值') {
  // ...
}

// 对象参数和默认值以及解构
function foo({ name, age, gender = '男' } = { name: 'liang', age: 20 }) {
  // ...
}

函数的 length 属性值为其参数数量,对于有参数默认值的函数,从有默认值的参数开始,后续参数不做数量统计。

// 对于有参数默认值的函数,从有默认值的参数开始,后续参数不做数量统计
function bar(a, b, c = 3) {}
console.log(bar.length) // 2
10. ES6 - 函数的剩余参数

ES6 中的剩余参数(Rest Parameter)是一种强大特性,可以将不定数量的参数放入到一个数组。

// 如果最后一个参数是以 ... 为前缀的,那么它会将剩余参数放到该参数中,并且作为一个数组
function foo(a, b, ...args) {
  console.log(a) // 1
  console.log(b) // 2
  console.log(args) // [3, 4, 5]
}
foo(1, 2, 3, 4, 5)
11. ES6 - 箭头函数的补充

箭头函数是没有显式原型的,所以不能作为构造函数,无法通过 new 来创建对象。

const foo = () => {}
console.log(foo.__proto__) // undefined
new foo() // Uncaught TypeError: foo is not a constructor
12. ES6 - 展开语法的使用

展开语法(Spread Syntax)最初在 ES6 中引入,主要用于数组操作,到了 ES9,展开语法被扩展到了对象处理。

// 1. 在函数调用时使用展开语法
function foo(a, b, c) {
  console.log({ a, b, c })
}
foo(...['html', 'css', 'js'])

// 2. 构造数组时
const name = 'liang'
const hobby = ['html', 'css']
const newArr = [...name, ...hobby]
console.log(newArr)

// 3. 构建对象字面量 ES9(ES2018)
const info = { name: 'liang', age: 20 }
const object = { title: 'profile', ...info, gender: 1 }
console.log(object)

展开运算符进行的是一个浅拷贝。

const info = { name: 'liang', profile: { age: 18 } }
const user = { ...info }
user.profile.age = 20
console.log(info.profile.age) // 20
13. ES6 - 二进制和八进制连接符
const num1 = 100 // 十进制
const num2 = 0b100 // 二进制
const num3 = 0o100 // 八进制
const num4 = 0x100 // 十六进制
console.log(num1) // 100
console.log(num2) // 4
console.log(num3) // 64
console.log(num4) // 256

// ES12(ES2011)对于大的数组,可以使用连接符 _
const num = 10_000_000_000
console.log(num) // 10000000000
14. ES6 - Symbol 数据类型的使用

Symbol 是 ES6 中新增的一个基本数据类型,翻译为:符号。

Symbol 即使多次创建值,它们也是不同的:Symbol 函数执行后,每次创建出来的值都是独一无二的。

// Symbol() 可以生成一个独一无二的值,可以让它作为对象的 key
const s1 = Symbol()
const s2 = Symbol()
console.log(s1 === s2) // false

// 创建 Symbol 值的时候传入一个描述
const s3 = Symbol('aaa')
console.log(s3.description) // aaa

Symbol 值作为对象的属性 key 的多种写法:

const s1 = Symbol()
const s2 = Symbol()
const s3 = Symbol()
const s4 = Symbol()
// 1. 在定义对象字面量时使用
const obj = {
  [s1]: '111',
  [s2]: '222'
}
// 2. 新增属性
obj[s3] = '333'
// 3. Object.defineProperty 方式
Object.defineProperty(obj, s4, {
  enumerable: true,
  configurable: true,
  writable: true,
  value: '444'
})
console.log(obj[s1]) // 111

前面我们说过,Symbol() 返回的值都是独一无二的,那么有没有办法让它返回相同的值呢?

Symbol.for(key) 是 ES6 中的一个静态方法,用于创建或查找全局注册表中的 Symbol。

// Symbol.for(key)
const s1 = Symbol.for('aaa')
const s2 = Symbol.for('aaa')
console.log(s1 === s2) // true
// Symbol.keyFor() 用于获取全局注册表中 Symbol 对应的键名
const key = Symbol.keyFor(s1)
console.log(key) // aaa
15. ES6 - 数据结构 Set(元素不可重复)

Set 是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是 Set 的元素不能重复。

// 通过构造函数创建 Set 结构
const set = new Set()
set.add(10)
set.add(20)
set.add(30)
set.add(30) // 不会被重复添加
console.log(set);

因为 Set 结构具有元素不会重复的特性,所以我们可以用于 数组去重。

// 利用 set 的特性去重
const arrSet = new Set([32, 10, 25, 10, 32, 15])
const newArr3 = [...arrSet]

Set 的常见属性和方法:

const set = new Set([32, 10, 25, 10, 32, 15])
console.log(set.size) // 4
set.add(18)
set.delete(10)
console.log(set.has(25)) // true
console.log(set) // Set(4) { 32, 25, 15, 18 }
16. ES6 - 数据结构 WeakSet(存放对象)

WeakSet 中只能存放对象类型,不能存放基本数据类型。WeakSet 对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么 GC 可以对该对象进行回收。

const weakSet = new WeakSet()
let obj = { name: 'liang' }
weakSet.add(obj)
17. ES6 - 数据结构 Map(支持对象属性 key)

Map 是一种新的数据结构,用于存储键值对,它与传统对象(Object)相比,具有更灵活的键类型和更好的性能特性。

const map = new Map()
map.set(user, 'aaa')
map.set(profile, 'bbb')
map.set('name', 'liang')
console.log(map)

Map 常见属性和方法:

const map = new Map([['name', 'liang'], ['music', '天空之外']])
console.log(map.size) // 2
map.set('age', 20).set('height', 190)
console.log(map.get('name')) // liang
console.log(map.has('age')) // true
map.delete('height')
map.clear()
console.log(map)
18. ES6 - 数据结构 WeakMap(key 只能是对象)

WeakMap 的 key 只能使用对象,不接受其他的类型作为 key。WeakMap 的 key 对对象的引用是弱引用,如果没有其他引用引用这个对象,那么 GC 可以回收该对象。

let obj2 = { name: 'liang' }
const map2 = new WeakMap()
map2.set(obj2, 'bbb')
obj2 = null
19. ES7 - Array.includes 方法和指数运算符

ES7 新增了 includes 方法,可以直接判断数据是否在数组中。

const arr = ['html', 'css', 'js']
if (arr.includes('css')) {
  console.log('在数组中')
}

ES7 新增的指数运算符:

// ES7 增加了一个运算符 **
console.log(2 ** 5)
20. ES8 - Object.values、Object.entries 方法

在 ES8 中提供了 Object.values() 来获取所有的 value 值。

const user = { name: 'liang', age: 20, height: 180 }
console.log(Object.keys(user)) // ['name', 'age', 'height']
console.log(Object.values(user)) // ['liang', 20, 180]

通过 Object.entries() 可以获取到一个数组,数组中会存放可以枚举属性的键值对数组。

console.log(Object.entries(user))
21. ES8 - String.padStart、String.padEnd 方法

在 ES8 中,引入了两个字符串方法:padStart、padEnd,用于在字符串的开头或结尾填充指定字符,使其达到指定长度。

const string = 'hello'
console.log(string.padStart(8))
console.log(string.padStart(8, '*'))
console.log(string.padEnd(8, '*'))

尾逗号(Trailing Commas)是指在数组、对象字面量或函数参数列表的最后一个元素后添加的额外逗号。

// ES8 才开始支持函数接收参数时或调用时最后面还有逗号
function foo(m, n,) {
  console.log({ m, n })
}
foo(111, 222,)
22. ES10 - Array.flat、Array.flatMap 方法

flat() 和 flatMap() 是两个用于处理数组扁平化的常用方法。

const nums = [1, [2], [[3]], [[[4]]]]
console.log(nums.flat(1))
console.log(nums.flat(2))
console.log(nums.flat(Infinity))

flatMap() 方法的使用方法:

const slogan = ['what are you doing', 'how old are you']
const words2 = slogan.flatMap(item => item.split(' '))
console.log(words2)
23. ES10 - Object.fromEntries、String.trimStart 方法

Object.fromEntries() 方法用于将键值对列表转换为一个普通对象。

const entries = Object.entries(user)
console.log(Object.fromEntries(entries))

清除字符串中的空格:

const string = ' hello world '
console.log({ trimStart: string.trimStart() })
console.log({ trimEnd: string.trimEnd() })
24. ES11 - 大整数类型 Bigint

在早期的 JavaScript 中,我们不能正确的表示过大的数字。大于 Number.MAX_SAFE_INTEGER 的数值,表示的值可能是不正确的。

// ES11 之后:Bigint(后面加一个 n)
const bigInt = 900719925474099100n
console.log(bigInt)
console.log(bigInt + 10n)
25. ES11 - 空值合并运算符 ??

空值合并运算符(Nullish Coalescing Operator),当左侧操作数为 null/undefined 时,返回右侧操作数。

let bar = 0
console.log(bar ?? 'hello') // 0
26. ES11 - 可选链操作符 ?.

ES11 进入了一个非常实用的特性:可选链操作符(Optional Chaining Operator)。

const profile = { name: 'liang' }
console.log(profile.info?.age)
27. ES11 - globalThis 和 for...in 标准化

globalThis 是 ES11 引入的一个标准化的全局对象引用,用于在任何 JavaScript 环境中统一访问全局对象。

// 浏览器环境
console.log(window)
// node 环境
console.log(global)
// ES11(在任何环境中都可以访问全局对象)
console.log(globalThis)
28. ES12 - FinalizationRegistry 执行清理回调

FinalizationRegistry 是 ES12 引入的一个高级特性,用于在对象被垃圾回收(GC)后执行清理回调。

let user = { name: 'liang' }
const finalRegistry = new FinalizationRegistry(() => {
  console.log('注册到 finalRegistry 的某个对象被销毁');
})
finalRegistry.register(user)
user = null
29. ES12 - WeakRef 创建对象的弱引用

WeakRef 是 ES12 引入的一个特性,用于创建对对象的弱引用。

let user = { name: 'liang' }
let info = new WeakRef(user)
console.log(info.deref())
30. ES12 - 逻辑赋值运算符、String.replaceAll()

JavaScript 中的三种逻辑赋值运算符是 ES12 引入的语法糖。

// 逻辑或赋值运算 ||= 
let message = ''
message ||= 'default'

// 逻辑与赋值运算 &&= 
let a = 1
let b = 2
a &&= b

// 空值合并赋值 ??= 
let c = ''
let d = 2
c ??= d

String.prototype.replaceAll() 是 ES12 引入的一个字符串方法。

const string = 'good idea good'
console.log(string.replaceAll('good', 'aaa'))
console.log(string.replaceAll(/good/g, 'bbb'))
31. ES13 - Array/String.at()、Object.hasOwn()

Array.prototype.at() 和 String.prototype.at() 是 ES13 引入的新方法,支持负数索引取值。

const arr = ['html', 'css', 'js', 'vue']
console.log(arr.at(-1)) // vue(最后一个)

ES13 中 Object 新增了一个静态方法(类方法):Object.hasOwn(obj, key)。

const user = { name: 'liang' }
console.log(Object.hasOwn(user, 'name')) // true
console.log(Object.hasOwn(user, 'age')) // false
32. ES13 - 类中新增的成员(私有化成员)

从 ES13 开始,正式支持在类中定义真正的私有化属性(private)。

class Person {
  height = 180
  #info = 'real private info'
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  running() {
    console.log(this.#info)
    this.#showName()
  }
  #showName() {
    console.log('name: ' + this.name);
  }
}
const p = new Person('liang', 20)
p.running()

类的静态属性、静态方法使用示例:

class Person {
  static name = 'liang'
  static #age = 20
  static showName() {
    console.log(this.#age);
  }
  static {
    console.log('hello world');
  }
}
console.log(Person.name)
Person.showName()

目录

  1. 1. ES6 - 对象字面量增强
  2. 2. ES6 - 对象和数组的解构
  3. 3. ES6 - let / const 的基本使用
  4. 4. ES6 - let / const 的作用域提升
  5. 5. ES6 - let / const 和 window 的关系
  6. 6. ES6 - 新增的块级作用域
  7. 7. ES6 - 模板字符串的使用
  8. 8. ES6 - 标签模板字符串
  9. 9. ES6 - 函数参数的默认值
  10. 10. ES6 - 函数的剩余参数
  11. 11. ES6 - 箭头函数的补充
  12. 12. ES6 - 展开语法的使用
  13. 13. ES6 - 二进制和八进制连接符
  14. 14. ES6 - Symbol 数据类型的使用
  15. 15. ES6 - 数据结构 Set(元素不可重复)
  16. 16. ES6 - 数据结构 WeakSet(存放对象)
  17. 17. ES6 - 数据结构 Map(支持对象属性 key)
  18. 18. ES6 - 数据结构 WeakMap(key 只能是对象)
  19. 19. ES7 - Array.includes 方法和指数运算符
  20. 20. ES8 - Object.values、Object.entries 方法
  21. 21. ES8 - String.padStart、String.padEnd 方法
  22. 22. ES10 - Array.flat、Array.flatMap 方法
  23. 23. ES10 - Object.fromEntries、String.trimStart 方法
  24. 24. ES11 - 大整数类型 Bigint
  25. 25. ES11 - 空值合并运算符 ??
  26. 26. ES11 - 可选链操作符 ?.
  27. 27. ES11 - globalThis 和 for...in 标准化
  28. 28. ES12 - FinalizationRegistry 执行清理回调
  29. 29. ES12 - WeakRef 创建对象的弱引用
  30. 30. ES12 - 逻辑赋值运算符、String.replaceAll()
  31. 31. ES13 - Array/String.at()、Object.hasOwn()
  32. 32. ES13 - 类中新增的成员(私有化成员)
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Open WebUI Docker 部署指南与最佳实践
  • C/C++ 动态规划入门:二维路径问题实战解析
  • RabbitMQ 事务机制与消息限流实战详解
  • Chrome 开发者工具(DevTools)快速入门
  • Spring Cloud Config 与 Apollo 配置中心架构深度解析
  • 基于机器学习的 Web 入侵检测系统设计与实现
  • OpenClaw 框架更新:三天三版支持 GPT-5.4 与记忆热插拔
  • Rust 安装与环境配置教程
  • Diff-eRank:基于有效秩的大模型去噪能力评估新指标
  • OpenClaw 智能体框架入门:环境搭建、模型配置与远程访问
  • Linux 内核源码下载指南:官方源、镜像加速与完整性校验
  • Lychee-Rerank-MM 本地部署教程:无网依赖图文重排序
  • 大模型时代企业 AI 发展趋势分析
  • Spring Boot 安全认证与授权核心解析
  • 深度学习环境搭建指南:PyTorch、Anaconda 与 GPU 配置
  • 开源电路板查看器 OpenBoardView:.brd 文件解析工具
  • Flash Attention 导入报错 undefined symbol 解决方案
  • Java 智慧养老系统:护理代办与陪诊全场景覆盖
  • Python 合并两个字典的 8 种常用方法
  • Microsoft Edge WebView2 环境安装与常见问题处理指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online