ECMAScript® 2015 Language Specification (ES6)
ES6官方文档,吃定它让你通吃ES6、阮一峰的入门笔记,当然也是一本很好学习es6基础的入门参考书籍了
在前端项目中,使用 ES6 语法能够提高代码的可读性和可维护性,同时也有助于减少错误,提升开发效率。随着现代前端框架(如 React、Vue、Angular)的流行,掌握 ES6 及其新特性已成为前端开发者的基本要求。
常用基础用法
1. 箭头函数 (Arrow Functions)
箭头函数提供了一种更简洁的函数表达方式,并且不绑定 this。
const sum = (a, b) => a + b;
const numbers = [1, 2, 3].map(num => num * 2);
2. 模板字符串 (Template Literals)
模板字符串使得字符串拼接和多行字符串的处理更加简便,使用反引号(``)语法。
const name = "Alice";
const greeting = `Hello, ${name}!`;
3. 解构赋值 (Destructuring Assignment)
解构赋值让我们能够快速提取数组或对象中的值,提升代码可读性。
// 对象解构
const user = { name: "Bob", age: 25 };
const { name, age } = user;
// 数组解构
const numbers = [1, 2, 3];
const [first, second] = numbers;
4. 扩展运算符 (Spread Operator)
扩展运算符用于数组和对象的合并或复制,使得操作更加简洁。
const array1 = [1, 2, 3];
const array2 = [...array1, 4, 5]; // [1, 2, 3, 4, 5]
const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 }; // { a: 1, b: 2 }
5. 默认参数 (Default Parameters)
函数参数可以设置默认值,避免未传入参数导致的错误。
const multiply = (x, y = 1) => x * y;
6. 模块化 (Modules)
ES6 引入了模块化,使得代码可以分割为多个文件,通过 export 和 import 进行管理。
// module.js
export const PI = 3.14;
// main.js
import { PI } from './module.js';
7. Promise
Promise 对象用于处理异步操作,提供了更好的错误处理和链式调用能力。
const fetchData = () => {
return new Promise((resolve, reject) => {
// 模拟异步请求
setTimeout(() => resolve("数据加载成功"), 1000);
});
};
fetchData().then(data => console.log(data));
8. 类 (Classes)
ES6 引入了类的概念,简化了对象的构造和继承的语法。
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
const dog = new Animal('Dog');
dog.speak();
9. 异步函数 (async/await)
async/await 使得处理异步操作更加直观,代码看起来更像同步代码。
const getData = async () => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
};
getData().then(data => console.log(data));
10. Set 和 Map
这两个数据结构可以更方便地处理唯一值和键值对。
const uniqueNumbers = new Set([1, 2, 2, 3]); // Set { 1, 2, 3 }
const map = new Map();
map.set('key1', 'value1');
console.log(map.get('key1')); // "value1"
11. WeakMap 和 weakSet
WeakSet 是一种类似于 Set 的集合类型,用于存储弱引用的对象。它具有以下特点:
- 只能存储对象,基本类型(如字符串、数字、布尔值等)不能存储。
- 存储的对象是弱引用,这意味着,如果没有其他对该对象的引用,垃圾回收器可以回收该对象,即使它仍在
WeakSet中。
// 创建一个 WeakSet
const weakSet = new WeakSet();
const obj1 = { id: 1 };
const obj2 = { id: 2 };
// 添加对象到 WeakSet
weakSet.add(obj1);
weakSet.add(obj2);
// 检查对象是否在 WeakSet 中
console.log(weakSet.has(obj1)); // true
console.log(weakSet.has(obj2)); // true
// 删除对象
weakSet.delete(obj1);
console.log(weakSet.has(obj1)); // false
// WeakSet不支持迭代,因此不能使用 forEach,也不能转换为数组
WeakMap 是一种类似于 Map 的数据结构,用于存储键值对。它具有以下特点:
- 键必须是对象,基本类型不能作为键。
- 键是弱引用,这意味着如果没有其他对该键的引用,垃圾回收器可以回收该键及其关联的值。
// 创建一个 WeakMap
const weakMap = new WeakMap();
const obj1 = {};
const obj2 = {};
// 设置键值对
weakMap.set(obj1, 'Value associated with obj1');
weakMap.set(obj2, 'Value associated with obj2');
// 获取值
console.log(weakMap.get(obj1)); // Value associated with obj1
console.log(weakMap.get(obj2)); // Value associated with obj2
// 检查键是否存在
console.log(weakMap.has(obj1)); // true
// 删除键值对
weakMap.delete(obj1);
console.log(weakMap.has(obj1)); // false
// WeakMap不支持迭代,因此不能使用 forEach,也不能转换为数组
- WeakSet 和 WeakMap 都允许存储对象,并且对这些对象的引用不是强引用。这意味着当没有其他引用指向这些对象时,它们可以被垃圾回收。
WeakSet只能存储对象,而WeakMap则是以对象作为键并可以存储与之关联的任意值。- 由于
WeakSet和WeakMap的特性,它们不支持迭代(比如没有forEach方法),也不能被转换为数组或其他可遍历的集合。
这些特性使 WeakSet 和 WeakMap 在需要频繁创建和销毁对象、并希望轻松管理内存时非常有用。
12. Symbol
Symbol 是一种新的原始数据类型,表示独一无二的值,常用于对象属性的唯一标识。
const uniqueSymbol = Symbol('description');
13. Iterators 和 Generators
迭代器提供了一种访问集合元素的统一接口,生成器函数(使用 function* 定义)可以控制函数的执行进程。
function* generatorFunc() {
yield 1;
yield 2;
}
const gen = generatorFunc();
console.log(gen.next().value); // 1
14. Proxy 和 Reflect
Proxy 允许你定义一个对象的代理,这样你可以拦截和自定义基本操作(如属性访问、赋值、调用等)。Proxy 接受两个参数:
- target:要代理的原始对象。
- handler:一个对象,定义了捕获器(interceptors),用于拦截代理对象的基本操作。
Reflect 是一个内置对象,提供了用于操作对象的方法,这些方法与 Proxy 的拦截方法相对应。Reflect 的方法通常用于在代理中调用,以确保对目标对象操作的一致性。
const target = {
name: "Alice",
age: 28
};
const handler = {
get(target, property) {
console.log(`Accessing property: ${property}`);
// 使用 Reflect 获取
return Reflect.get(target, property);
},
set(target, property, value) {
console.log(`Updating property: ${property} to ${value}`);
// 使用 Reflect 设置
return Reflect.set(target, property, value);
},
deleteProperty(target, property) {
console.log(`Deleting property: ${property}`);
// 使用 Reflect 删除
return Reflect.deleteProperty(target, property);
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // Accessing property: name \n Alice
proxy.age = 30; // Updating property: age to 30
console.log(proxy.age); // Accessing property: age \n 30
delete proxy.name; // Deleting property: name
console.log(proxy.name); // Accessing property: name \n undefined
15. let 和 const
let 和 const 是 ES6(ECMAScript 2015)中引入的用于声明变量的两种命令。它们相较于传统的 var 关键字有着更严格的作用域管理和更清晰的变量行为。
let
概述
let用于声明变量,具有块级作用域,也就是说,它仅在定义它的代码块内有效。let声明的变量可以被重新赋值。
{
let x = 10;
console.log(x); // 10
}
console.log(x); // ReferenceError: x is not defined
let y = 5;
y = 15; // 合法的重新赋值
console.log(y); // 15
2. const
概述
const用于声明常量,同样具有块级作用域。声明使用const的变量后,必须在声明时初始化。const声明的变量不能被重新赋值。需要注意的是,const只保证变量的引用不可变,若引用的是对象,仍然可以修改对象的属性。
{
const z = 20;
console.log(z); // 20
}
console.log(z); // ReferenceError: z is not defined
const a = 30;
// a = 40; // TypeError: Assignment to constant variable.
const obj = { name: "Alice" };
obj.name = "Bob"; // 合法,修改对象属性
console.log(obj.name); // Bob
3. 总结对比
-
作用域:
let和const都是块级作用域,而var是函数作用域。
-
赋值:
let允许变量重新赋值。const不允许重新赋值,必须初始化。
-
使用建议:
- 使用
const声明常量,明确变量不应该被修改,能提高代码的可维护性。 - 使用
let声明会被修改的变量。
- 使用
4. 注意事项
- 使用
let和const时会存在 "暂时性死区" 的现象。这意味着在变量声明之前访问变量会导致错误。
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 10;
总结来说,let 和 const 提供了更严格的变量管理,鼓励使用块级作用域,增强了代码的安全性和可维护性。在现代 JavaScript 开发中,推荐使用 let 和 const,避免使用 var。
16. 迭代器和生成器
迭代器
迭代器是一个对象,它提供了一种机制,用于逐个访问一个集合(如数组、对象等)中的元素,而不需要暴露集合的内部结构。迭代器的核心在于它实现了一个方法——next(),每次调用此方法都会返回一个包含当前元素的对象。这个对象通常具有两个属性:
value:当前迭代的值。done:一个布尔值,表示迭代是否完成。如果还有更多的元素可供迭代,则为false;如果没有更多元素,则为true。
const myIterator = {
current: 0,
last: 5,
next: function() {
if (this.current < this.last) {
return { value: this.current++, done: false };
} else {
return { value: undefined, done: true };
}
}
};
// 使用迭代器 从 `0` 循环到 `4`,使用 `next()` 方法返回当前值并递增
console.log(myIterator.next()); // { value: 0, done: false }
console.log(myIterator.next()); // { value: 1, done: false }
console.log(myIterator.next()); // { value: 2, done: false }
console.log(myIterator.next()); // { value: 3, done: false }
console.log(myIterator.next()); // { value: 4, done: false }
console.log(myIterator.next()); // { value: undefined, done: true }
生成器
生成器是一种特殊的函数,使用 function* 语法定义,可以在执行过程中暂停和恢复。这使得生成器函数能够生成一个迭代器,而不需要显式地实现 next() 方法。生成器函数中可以使用 yield 关键字来返回一个值,每当调用生成器的 next() 方法时,函数会从上次暂停的地方继续执行,直到遇到下一个 yield 或者函数结束。
function* myGenerator() {
let current = 0;
const last = 5;
while (current < last) {
yield current++;
}
}
// 使用生成器 在其中使用 `yield` 关键字来生成值 每次调用 `next()` 方法时,会返回一个对象,包含当前值和 `done` 状态
const gen = myGenerator();
console.log(gen.next()); // { value: 0, done: false }
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: 4, done: false }
console.log(gen.next()); // { value: undefined, done: true }
对比
1. 箭头函数和普通函数的区别
- 语法:箭头函数的语法更简洁,适合短小的函数。
this绑定:箭头函数不绑定自己的this,自动继承外层函数的this。- 构造函数:箭头函数不能被用作构造函数(不能使用
new关键字创建实例)。 arguments:箭头函数没有自己的arguments对象(箭头函数不具有自己的arguments对象。如果需要访问参数,可以使用 rest 参数语法)。- 不能使用
super和new.target(在箭头函数内部,不能使用super和new.target,这意味着箭头函数不能用于类的继承)。 - 隐式返回:箭头函数可使用隐式返回(当函数体只有一行代码时,可以省略
return和{})。
2. export、export default、import 和 import * as xxx 的区别
export:用于导出多个命名的变量、函数或类。export default:用于导出一个默认值 (可以是变量、函数或类),每个模块只能有一个默认导出。import:用于引入从模块中导出的命名或默认的值。import * as xxx:将模块中所有的命名导出引入,并收集在指定的对象中,方便通过这个对象访问所有导出的内容。
3. let、const、var 的区别
- 作用域:
var是函数作用域,let和const是块级作用域。 - 重新赋值:
var和let可以重新赋值,const不允许重新赋值。 - 提升:
var允许在声明之前使用,但值为undefined;let和const在被初始化之前不能访问。 - 重复声明:
var允许重复声明,let和const不允许
4. proxy 与 defineproperty 的区别
功能与用途
-
Proxy:Proxy是一种用于创建对象的代理,它可以拦截并自定义对目标对象基本操作(如属性访问、赋值、删除、函数调用等)的行为。- 支持对整个对象的操作,包括对嵌套对象的属性及方法的拦截。
- 可以用来实现数据绑定、监听变化、访问控制等复杂逻辑。
-
Object.defineProperty:Object.defineProperty用于直接在对象上定义新属性或修改现有属性并返回该对象。它可以控制属性的描述符,比如可写性、可枚举性和可配置性。- 适用于设置单个属性的特性,而不适用于对整个对象的拦截。
监听能力
-
Proxy:Proxy可以拦截多种操作,例如获取(get)、设置(set)、删除(deleteProperty)、调用(apply)等,可以更广泛地管理对象的操作。
-
Object.defineProperty:- 主要用来定义或修改单个属性,无法拦截属性的获取或设置操作,只能修改该属性的特性。
多个属性与嵌套对象
-
Proxy:- 可以对整个对象及其所有嵌套属性进行操作和拦截,非常灵活。
-
Object.defineProperty:- 对于属性的操作是单一的,不能批量定义或修改多个属性,也不能直接应用于嵌套对象。
性能
-
Proxy:- 在某些操作中可能会带来额外的性能开销,因为每次操作都需要通过拦截器处理。
-
Object.defineProperty:- 由于直接操作对象属性,对于单个属性的定义和修改性能较高。
兼容性
Object.defineProperty具有更好的浏览器兼容性,适用于需要广泛支持的情况。Proxy由于不支持老旧浏览器(尤其是 IE),在需要兼容性时应谨慎使用,但可以用来进行更复杂的对象操作。对于现代浏览器的应用开发,一般推荐使用Proxy,而在需要支持较旧环境时优先考虑Object.defineProperty。
5. WeakSet 和 WeakMap 和 Map 和 Set 的区别
| 特性 | Set | WeakSet | Map | WeakMap |
|---|---|---|---|---|
| 存储类型 | 任何类型 | 仅限对象 | 任何类型 | 仅限对象(作为键) |
| 引用类型 | 强引用 | 弱引用 | 强引用 | 弱引用 |
| 是否支持迭代 | 支持 | 不支持 | 支持 | 不支持 |
| 是否可以用基本类型 | 可以 | 不可以 | 可以 | 不可以 |
| 键值对 | 无 | 无 | 键值对 | 键值对 |
使用场景
-
Set 和 WeakSet:
Set适用于需要存储唯一值的场景,如去重。WeakSet适用于需要存储对对象的弱引用,并跟踪哪些对象仍在使用,用于实现一些内存管理的功能。
-
Map 和 WeakMap:
Map适用于需要用任何类型的键存储和访问数据的情况,支持可迭代操作。WeakMap则适合在需要存储对象的元数据或缓存时使用,并希望避免因对象的引用而导致的内存泄漏。
6. 迭代器和生成器的区别
迭代器
-
定义:迭代器是一个对象,它实现了
next()方法,每次调用这个方法时都返回一个对象,该对象包含两个属性:value:当前迭代的值。done:一个布尔值,表示迭代是否完成。
-
实现:为了创建一个迭代器,你需要手动实现一个对象,并定义
next()方法。 -
用途:迭代器提供了一种统一的遍历方法,可以用于任何可迭代对象(如数组、字符串、Map、Set等)。
生成器
- 定义:生成器是一种特殊类型的函数,使用
function*语法定义。它可以暂停和恢复执行,同时会自动生成迭代器对象。 - 实现:通过
yield关键字,可以在生成器函数中暂停执行并返回一个值。下一次调用next()方法时,会从上一次暂停的地方恢复执行。 - 用途:生成器可以方便地生成序列、处理异步操作等,提供了比常规函数更灵活的控制流。
额外的一些常用的方法和特性
字符串相关
1. startsWith()
检查字符串是否以指定的字符序列开头。
const str = 'Hello, world!';
console.log(str.startsWith('Hello')); // true
console.log(str.startsWith('world')); // false
2. endsWith()
检查字符串是否以指定的字符序列结尾。
console.log(str.endsWith('world!')); // true
console.log(str.endsWith('Hello')); // false
3. includes()
判断字符串是否包含指定的字符序列。
console.log(str.includes('lo')); // true
console.log(str.includes('world')); // true
console.log(str.includes('JavaScript')); // false
4. repeat()
创建一个新字符串,表示将原字符串重复指定次数。
const repeatedStr = 'abc'.repeat(3);
console.log(repeatedStr); // 'abcabcabc'
5. padStart() 和 padEnd()
这两个方法用于在当前字符串的两端填充指定的字符,使最终字符串达到指定的长度。
padStart(targetLength, padString):在当前字符串的开头填充字符。
const str1 = '5';
console.log(str1.padStart(2, '0')); // '05'
padEnd(targetLength, padString):在当前字符串的结尾填充字符。
const str2 = '5';
console.log(str2.padEnd(2, '0')); // '50'
6. String.raw()
这是一个标签模板字面量的辅助函数,用于处理模板字符串中的转义字符。
const rawStr = String.raw`Hello\nWorld`;
console.log(rawStr); // 'Hello\nWorld'
对象相关
1. 对象字面量增强
- 简写属性:在对象字面量中,如果属性名和变量名相同,可以省略属性名。
const x = 1;
const y = 2;
const obj = { x, y }; // 等同于 { x: x, y: y }
console.log(obj); // { x: 1, y: 2 }
- 方法简写:定义对象的方法时,可以省略
function关键字。
const obj = {
greet() {
console.log('Hello!');
}
};
obj.greet(); // 'Hello!'
- 计算属性名:可以使用表达式作为属性名。
const prop = 'name';
const obj = {
[prop]: 'Alice'
};
console.log(obj.name); // 'Alice'
2. Object.is()
用于判断两个值是否严格相等,它比 === 更加严格。例如,NaN 与 NaN 被认为是相等的,而 +0 和 -0 被认为是不相等的。
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(+0, -0)); // false
console.log(Object.is('a', 'a')); // true
3. Object.assign()
用于将一个或多个源对象的可枚举属性复制到目标对象中,返回目标对象。
const target = { a: 1 };
const source = { b: 2 };
Object.assign(target, source);
console.log(target); // { a: 1, b: 2 }
4. Object.entries()
将一个对象的可枚举属性转换为一个二维数组,其中每个元素是一个 [key, value] 对。
const obj = { a: 1, b: 2 };
const entries = Object.entries(obj);
console.log(entries); // [['a', 1], ['b', 2]]
5. Object.values()
返回一个包含对象自身可枚举属性值的数组。
const obj = { a: 1, b: 2 };
const values = Object.values(obj);
console.log(values); // [1, 2]
6. Object.freeze()
使一个对象成为不可变的,不能更改其属性(即添加、删除或修改属性)。
const obj = { a: 1 };
Object.freeze(obj);
obj.a = 2; // 无效
console.log(obj.a); // 1
7. Object.seal()
将一个对象密封,不能添加或删除属性,但可以修改现有属性的值。
const obj = { a: 1 };
Object.seal(obj);
obj.a = 2; // 可以修改
delete obj.a; // 无效
console.log(obj.a); // 2
8. Object.getOwnPropertyDescriptors()
返回一个对象的所有属性描述符。
const obj = { a: 1 };
const descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors); // { a: { value: 1, writable: true, enumerable: true, configurable: true } }
数值相关
1. Number.isFinite()
用于检查一个值是否是有限的数字。与全局的 isFinite() 方法不同,它不会在类型转换上进行处理。
console.log(Number.isFinite(10)); // true
console.log(Number.isFinite('10')); // false
console.log(Number.isFinite(NaN)); // false
console.log(Number.isFinite(Infinity)); // false
2. Number.isInteger()
用于检查一个值是否是一个整数。
console.log(Number.isInteger(4)); // true
console.log(Number.isInteger(4.1)); // false
console.log(Number.isInteger('4')); // false
console.log(Number.isInteger(NaN)); // false
3. Number.isSafeInteger()
用于检查一个值是否是一个安全的整数。安全整数是指大于或等于 -(2^53 - 1) 并且小于或等于 2^53 - 1 的整数。
console.log(Number.isSafeInteger(3)); // true
console.log(Number.isSafeInteger(Math.pow(2, 53))); // false
console.log(Number.isSafeInteger(Math.pow(2, 53) - 1)); // true
4. Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER
这两个属性表示 JavaScript 中安全整数的最大和最小值。
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
5. Math.trunc()
返回一个数值的整数部分,通过删除小数部分。
console.log(Math.trunc(4.9)); // 4
console.log(Math.trunc(-4.9)); // -4
console.log(Math.trunc(4)); // 4
6. Math.sign()
用于判断一个数的符号。返回值为 1 表示正数,-1 表示负数,0 表示零,NaN 表示不是一个数字。
console.log(Math.sign(5)); // 1
console.log(Math.sign(-5)); // -1
console.log(Math.sign(0)); // 0
console.log(Math.sign(-0)); // -0
console.log(Math.sign(NaN)); // NaN
7. Math.cbrt()
返回一个数的立方根。
console.log(Math.cbrt(27)); // 3
console.log(Math.cbrt(-27)); // -3
8. Math.hypot()
计算所有参数的平方和的平方根,可以用于计算欧几里得距离。
console.log(Math.hypot(3, 4)); // 5
console.log(Math.hypot(1, 2, 3)); // 3.7416573867739413
console.log(Math.hypot(3, 4, 'five')); // 5
9. Math.imul()
用于计算两个 32 位整数的乘法,结果也是一个 32 位整数。
console.log(Math.imul(2, 4)); // 8
console.log(Math.imul(0xFFFFFFFF, 5)); // -5,因为结果超出了 32 位整数范围
数组相关
1. 数组的解构赋值
允许从数组中提取值到变量中,这样可以简化代码。
const arr = [1, 2, 3];
const [a, b, c] = arr;
console.log(a, b, c); // 1 2 3
2. 数组的扩展运算符 ...
扩展运算符可以展开数组,常用于函数参数、数组连接等场景。
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [...arr1, ...arr2];
console.log(arr3); // [1, 2, 3, 4, 5, 6]
3. Array.from()
该方法可以将类数组对象或可迭代对象转换为数组。
const str = 'hello';
const arr = Array.from(str);
console.log(arr); // ['h', 'e', 'l', 'l', 'o']
4. Array.of()
用于创建一个新数组,接受任意数量的参数并将它们作为数组元素。
const arr = Array.of(7, 8, 9);
console.log(arr); // [7, 8, 9]
5. copyWithin()
用于在数组内部复制指定位置的元素到另一个位置(会覆盖原有元素),而不改变数组长度。
const arr = [1, 2, 3, 4, 5];
arr.copyWithin(0, 3);
console.log(arr); // [4, 5, 3, 4, 5]
6. find() 和 findIndex()
find() 方法用于查找数组中满足提供的测试函数的第一个元素,而 findIndex() 则返回满足条件的第一个元素的索引。
const arr = [5, 12, 8, 130, 44];
const found = arr.find(element => element > 10);
console.log(found); // 12
const index = arr.findIndex(element => element > 10);
console.log(index); // 1
7. fill()
该方法用于用一个静态值填充数组中的指定元素,改变原数组。
const arr = new Array(3).fill(0); // [0, 0, 0]
console.log(arr);
8. entries()
返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的键值对。
const arr = ['a', 'b', 'c'];
const iterator = arr.entries();
for (const [index, element] of iterator) {
console.log(index, element);
}
// 输出:
// 0 'a'
// 1 'b'
// 2 'c'
9. includes()
判断数组是否包含某个元素,返回布尔值。
const arr = [1, 2, 3];
console.log(arr.includes(2)); // true
console.log(arr.includes(4)); // false
10. keys() 和 values()
keys()方法返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的键。values()方法返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的值。
const arr = ['a', 'b', 'c'];
for (const key of arr.keys()) {
console.log(key); // 0 1 2
}
for (const value of arr.values()) {
console.log(value); // 'a' 'b' 'c'
}
运算符相关
-
解构赋值(Destructuring Assignment):允许从数组或对象中提取数据并直接分配给变量。
const [a, b] = [1, 2]; console.log(a); // 1 console.log(b); // 2 const {name, age} = {name: 'Alice', age: 30}; console.log(name); // Alice -
扩展运算符(Spread Operator) (
...):可以将数组或对象的内容展开const arr1 = [1, 2, 3]; const arr2 = [...arr1, 4, 5]; console.log(arr2); // [1, 2, 3, 4, 5] const obj1 = {x: 10, y: 20}; const obj2 = {...obj1, z: 30}; console.log(obj2); // {x: 10, y: 20, z: 30} -
剩余参数(Rest Parameters)(
...):在函数定义中收集传递给函数的多余参数到一个数组中function sum(...numbers) { return numbers.reduce((acc, curr) => acc + curr, 0); } console.log(sum(1, 2, 3, 4)); // 10 -
空值合并运算符(Nullish Coalescing Operator) (
??):虽然不是ES6的一部分,但在ES2020中引入,用于处理null或undefined值const value = null ?? 'default'; console.log(value); // 'default' -
可选链式调用(Optional Chaining) (
?.):同样不是ES6的特性,但在ES2020中引入,允许安全地访问深层嵌套的对象属性const user = {name: 'Alice'}; console.log(user.address?.street); // undefined