1. let 和 const
let
和 const
是用来声明变量的新方式,它们提供了块级作用域。
// let
let x = 10;
if (true) {
let x = 20;
console.log(x); // 20
}
console.log(x); // 10
// const
const y = 30;
// y = 40; // TypeError: Assignment to constant variable.
const obj = { a: 1 };
obj.a = 2; // 允许修改对象的属性
console.log(obj.a); // 2
2. 箭头函数
箭头函数提供了一种更简洁的函数表达方式,并且不会绑定自己的 this
。
const add = (a, b) => a + b;
console.log(add(2, 3)); // 5
const numbers = [1, 2, 3, 4];
const squares = numbers.map(n => n * n);
console.log(squares); // [1, 4, 9, 16]
// 使用箭头函数避免 this 问题
function Timer() {
this.seconds = 0;
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
new Timer();
3. 模板字符串
模板字符串提供了嵌入表达式和多行字符串的功能。
const name = 'John';
const greeting = `Hello, ${name}!`;
console.log(greeting); // Hello, John!
const multiline = `This is a
multiline string.`;
console.log(multiline);
// This is a
// multiline string.
// 嵌入表达式
const a = 5;
const b = 10;
console.log(`The sum of ${a} and ${b} is ${a + b}.`); // The sum of 5 and 10 is 15.
4. 解构赋值
解构赋值允许从数组或对象中提取数据,并将其赋值给变量。
// 数组解构
const [a, b] = [1, 2];
console.log(a, b); // 1 2
const [c, d, e = 5] = [3, 4];
console.log(c, d, e); // 3 4 5
// 对象解构
const { name, age } = { name: 'Alice', age: 25 };
console.log(name, age); // Alice 25
const { x = 10, y = 20 } = { x: 5 };
console.log(x, y); // 5 20
// 解构赋值中的嵌套对象
const user = {
name: 'John',
address: {
street: '123 Main St',
city: 'New York'
}
};
const { name: userName, address: { street, city } } = user;
console.log(userName); // John
console.log(street); // 123 Main St
console.log(city); // New York
5. 默认参数
函数参数可以有默认值。
function greet(name = 'Guest') {
return `Hello, ${name}!`;
}
console.log(greet()); // Hello, Guest!
console.log(greet('Alice')); // Hello, Alice!
// 使用默认参数计算
function multiply(a, b = 1) {
return a * b;
}
console.log(multiply(5)); // 5
console.log(multiply(5, 2)); // 10
6. 展开运算符
展开运算符用于展开数组或对象。
// 数组展开
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4];
console.log(arr2); // [1, 2, 3, 4]
// 对象展开
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };
console.log(obj2); // { a: 1, b: 2, c: 3 }
// 函数参数展开
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
// 数组拷贝和合并
const fruits = ['apple', 'banana'];
const moreFruits = ['orange', 'pear'];
const combinedFruits = [...fruits, ...moreFruits];
console.log(combinedFruits); // ['apple', 'banana', 'orange', 'pear']
7. Promise
Promise
是用于处理异步操作的新方式。它代表一个未来完成(或失败)的操作以及它的结果值。
创建 Promise
创建一个 Promise
实例,并用 resolve
和 reject
控制成功和失败。
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Success!');
}, 1000);
});
promise.then(result => {
console.log(result); // Success!
}).catch(error => {
console.error(error);
});
链式调用
Promise
可以通过 then
链式调用多个处理器。
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 1000);
});
promise
.then(result => {
console.log(result); // 1
return result + 1;
})
.then(result => {
console.log(result); // 2
return result + 1;
})
.then(result => {
console.log(result); // 3
})
.catch(error => {
console.error(error);
});
错误处理
可以通过 catch
来捕获 Promise
中的错误。
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject('Something went wrong!');
}, 1000);
});
promise
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error); // Something went wrong!
});
Promise.all
Promise.all
方法接收一组 Promise
,并返回一个新的 Promise
,当所有 Promise
完成时,新的 Promise
将以一个数组的形式返回结果。
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);
Promise.all([promise1, promise2, promise3])
.then(results => {
console.log(results); // [1, 2, 3]
})
.catch(error => {
console.error(error);
});
Promise.race
Promise.race
方法接收一组 Promise
,并返回一个新的 Promise
,只要一个 Promise
完成或失败,新 Promise
就会以第一个完成或失败的结果值来结束。
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('First promise resolved');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Second promise resolved');
}, 500);
});
Promise.race([promise1, promise2])
.then(result => {
console.log(result); // Second promise resolved
})
.catch(error => {
console.error(error);
});
8. async 和 await
async
和 await
使处理异步代码更加简洁。
基本使用
一个 async
函数会返回一个 Promise
。await
关键字只能在 async
函数内部使用,用于等待一个 Promise
完成。
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
fetchData();
串行执行
await
关键字可以串行执行多个异步操作,保证代码按顺序执行。
async function fetchMultipleData() {
try {
const response1 = await fetch('https://api.example.com/data1');
const data1 = await response1.json();
console.log(data1);
const response2 = await fetch('https://api.example.com/data2');
const data2 = await response2.json();
console.log(data2);
} catch (error) {
console.error('Error:', error);
}
}
fetchMultipleData();
并行执行
可以使用 Promise.all
并行执行多个异步操作,提高性能。
async function fetchParallelData() {
try {
const [response1, response2] = await Promise.all([
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2')
]);
const data1 = await response1.json();
const data2 = await response2.json();
console.log(data1);
console.log(data2);
} catch (error) {
console.error('Error:', error);
}
}
fetchParallelData();
9. 类(Class)
class
提供了更简洁的面向对象编程语法。
定义类
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
}
}
const john = new Person('John', 30);
console.log(john.greet()); // Hello, my name is John and I am 30 years old.
继承
使用 extends
关键字实现类的继承,子类可以继承父类的属性和方法。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
}
}
class Student extends Person {
constructor(name, age, grade) {
super(name, age); // 调用父类的构造函数
this.grade = grade;
}
study() {
return `${this.name} is studying in grade ${this.grade}.`;
}
}
const alice = new Student('Alice', 20, 'A');
console.log(alice.greet()); // Hello, my name is Alice and I am 20 years old.
console.log(alice.study()); // Alice is studying in grade A.
静态方法
使用 static
关键字定义静态方法,静态方法可以直接通过类调用,而不是通过类实例。
class MathHelper {
static add(a, b) {
return a + b;
}
static subtract(a, b) {
return a - b;
}
}
console.log(MathHelper.add(2, 3)); // 5
console.log(MathHelper.subtract(5, 2)); // 3
10. 模块化
ES6 引入了模块化语法,允许将代码分割成更小的文件。
导出和导入
// math.js
export function add(a, b) {
return a + b;
}
export const PI = 3.14;
// main.js
import { add, PI } from './math.js';
console.log(add(2, 3)); // 5
console.log(PI); // 3.14
默认导出
模块可以有一个默认导出,使用 export default
语法。
// math.js
export default function multiply(a, b) {
return a * b;
}
// main.js
import multiply from './math.js';
console.log(multiply(2, 3)); // 6
动态导入
动态导入允许在运行时按需加载模块。
// main.js
async function loadModule() {
const { add } = await import('./math.js');
console.log(add(2, 3)); // 5
}
loadModule();
11. 可选链操作符
可选链操作符 ?.
允许在链式调用时更安全地访问深层次的对象属性。
const user = {
address: {
street: '123 Main St'
}
};
console.log(user?.address?.street); // 123 Main St
console.log(user?.contact?.phone); // undefined
12. 空值合并操作符
空值合并操作符 ??
提供了一种更简洁的方式来处理 null
或 undefined
。
const name = null;
const defaultName = 'Guest';
console.log(name ?? defaultName); // Guest
const age = 0;
const defaultAge = 18;
console.log(age ?? defaultAge); // 0
13. 私有字段
私有字段以 #
开头,只能在类的内部访问。
class Person {
#name;
constructor(name) {
this.#name = name;
}
greet() {
return `Hello, my name is ${this.#name}.`;
}
}
const alice = new Person('Alice');
console.log(alice.greet()); // Hello, my name is Alice.
// console.log(alice.#name); // SyntaxError: Private field '#name' must be declared in an enclosing class
14. BigInt
BigInt 是一种新的原始数据类型,用于表示任意精度的整数。
const bigInt = 1234567890123456789012345678901234567890n;
console.log(bigInt); // 1234567890123456789012345678901234567890n
const sum = bigInt + 10n;
console.log(sum); // 1234567890123456789012345678901234567900n
// 将现有的Number转换为BigInt
const num = 42;
const bigIntNum = BigInt(num);
console.log(bigIntNum); // 42n
15. 动态导入
动态导入允许在运行时按需加载模块。
// main.js
async function loadModule() {
const { add } = await import('./math.js');
console.log(add(2, 3)); // 5
}
loadModule();
16. Symbol
Symbol
是一种新的原始数据类型,表示独一无二的值。
const sym1 = Symbol('description');
const sym2 = Symbol('description');
console.log(sym1 === sym2); // false
const obj = {
[sym1]: 'value1'
};
console.log(obj[sym1]); // value1
17. Set 和 Map
Set
是一种新的集合类型,Map
是一种新的键值对集合类型。
// Set
const set = new Set([1, 2, 3, 3]);
console.log(set.size); // 3
set.add(4);
set.delete(2);
console.log(set.has(2)); // false
for (const value of set) {
console.log(value); // 1 3 4
}
// Map
const map = new Map([['key1', 'value1'], ['key2', 'value2']]);
console.log(map.get('key1')); // value1
map.set('key3', 'value3');
map.delete('key2');
console.log(map.has('key2')); // false
for (const [key, value] of map) {
console.log(key, value); // key1 value1, key3 value3
}
18. WeakSet 和 WeakMap
WeakSet
和 WeakMap
是特殊的集合和键值对集合,不会阻止其包含的对象被垃圾回收。
// WeakSet
const weakSet = new WeakSet();
let obj = { foo: 'bar' };
weakSet.add(obj);
console.log(weakSet.has(obj)); // true
obj = null; // 对象被垃圾回收
console.log(weakSet.has(obj)); // false
// WeakMap
const weakMap = new WeakMap();
let keyObj = { key: 'value' };
weakMap.set(keyObj, 'some value');
console.log(weakMap.get(keyObj)); // some value
keyObj = null; // 对象被垃圾回收
console.log(weakMap.get(keyObj)); // undefined