ES6:现代 JavaScript 开发的基石与全新体验
ECMAScript 2015(简称 ES6)是 JavaScript 语言的一次里程碑式更新,它不仅引入了大量新语法和特性,更从根本上改变了 JavaScript 的开发方式和体验。十多年过去了,这些特性已成为现代前端开发的标配。让我们一起探索 ES6 如何让 JavaScript 从"能用"变得"优雅而强大"。
一、基础革新:更安全、更清晰的语法
1. 变量声明:告别 var 的梦魇
ES6 引入了 let 和 const,解决了 var 的变量提升和函数作用域带来的困惑。
javascript
// 以前:var 带来的困惑
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 输出 3, 3, 3
}
// 现在:let 的块级作用域
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 输出 0, 1, 2
}
// const 用于常量声明(注意:对象属性可修改)
const API_URL = 'https://api.example.com';
const config = { theme: 'dark' };
config.theme = 'light'; // 允许,因为修改的是对象属性
// config = {}; // 报错:不能重新赋值
核心要点 :默认使用 const,需要重新赋值时用 let,基本不用 var。
2. 箭头函数:简洁的语法与确定的 this
箭头函数不仅语法简洁,更重要的是它继承了定义时的 this 值。
javascript
// 传统函数的问题
function Counter() {
this.count = 0;
setInterval(function() {
this.count++; // 这里的 this 指向 window/global,不是 Counter 实例!
console.log(this.count);
}, 1000);
}
// 箭头函数的解决方案
function Counter() {
this.count = 0;
setInterval(() => {
this.count++; // 正确指向 Counter 实例
console.log(this.count);
}, 1000);
}
// 简洁的语法
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2); // [2, 4, 6]
const sum = (a, b) => a + b;
注意 :箭头函数没有自己的 this、arguments、super,不能用作构造函数。
二、让代码更优雅:模板字符串与解构赋值
3. 模板字符串:告别字符串拼接的混乱
javascript
// 以前:繁琐的拼接
const name = 'Alice';
const age = 25;
const message = 'Hello, ' + name + '! You are ' + age + ' years old.';
// 现在:清晰的模板字符串
const message = `Hello, ${name}! You are ${age} years old.`;
// 支持多行字符串,特别适合 HTML 模板
const html = `
<div class="user-card">
<h2>${name}</h2>
<p>Age: ${age}</p>
<p>Joined: ${new Date().toLocaleDateString()}</p>
</div>
`;
// 甚至可以在 ${} 中执行表达式
const score = 85;
const result = `Your grade is ${score >= 60 ? 'Pass' : 'Fail'}`;
4. 解构赋值:优雅的数据提取
javascript
// 数组解构
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [3, 4, 5]
// 对象解构 - 最实用的特性之一
const user = {
id: 1,
name: 'John',
age: 30,
email: 'john@example.com'
};
// 提取需要的属性
const { name, email } = user;
console.log(name, email); // 'John' 'john@example.com'
// 重命名 + 默认值
const { name: userName, role = 'user' } = user;
// 函数参数解构 - 让函数签名更清晰
function createUser({ name, age, email = 'default@example.com' }) {
console.log(`Creating user: ${name}, ${age}, ${email}`);
}
// 嵌套解构
const company = {
name: 'Tech Corp',
employees: [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
]
};
const {
name: companyName,
employees: [{ name: firstEmployeeName }]
} = company;
三、函数增强:默认参数与剩余参数
5. 默认参数与剩余参数
javascript
// 默认参数:不再需要 || 操作符
function greet(name = 'Guest', greeting = 'Hello') {
console.log(`${greeting}, ${name}!`);
}
greet(); // "Hello, Guest!"
// 剩余参数:替代 arguments 对象
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
// 实际应用:组合函数参数
function formatUserInfo(name, age, ...hobbies) {
return {
name,
age,
hobbies,
hobbyCount: hobbies.length
};
}
四、对象与数组的增强
6. 展开运算符:连接、复制与合并
javascript
// 数组操作
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// 对象操作(浅拷贝)
const original = { a: 1, b: 2 };
const copy = { ...original }; // 浅拷贝
const updated = { ...original, b: 3, c: 4 }; // { a: 1, b: 3, c: 4 }
// 函数调用
const numbers = [1, 2, 3];
console.log(Math.max(...numbers)); // 3
7. 对象字面量增强
javascript
// 属性简写:变量名作为属性名
const name = 'Alice';
const age = 25;
const user = { name, age }; // { name: 'Alice', age: 25 }
// 方法简写
const calculator = {
add(a, b) { return a + b; }, // 相当于 add: function(a, b) { ... }
multiply(a, b) { return a * b; }
};
// 计算属性名
const prefix = 'user_';
const dynamicKeys = {
[prefix + 'id']: 1,
[prefix + 'name']: 'Alice',
['get' + 'FullName']() {
return `${this.user_name}`;
}
};
五、异步编程的新时代:Promise
8. Promise:告别回调地狱
javascript
// 传统回调地狱
getUser(userId, function(user) {
getPosts(user.id, function(posts) {
getComments(posts[0].id, function(comments) {
console.log(comments);
});
});
});
// Promise 链式调用
getUser(userId)
.then(user => getPosts(user.id))
.then(posts => getComments(posts[0].id))
.then(comments => console.log(comments))
.catch(error => console.error('Something went wrong:', error));
// 创建 Promise
function fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then(response => {
if (response.ok) {
resolve(response.json());
} else {
reject(new Error('Network response was not ok'));
}
})
.catch(reject);
});
}
// Promise 实用方法
// 并行执行,所有成功才成功
Promise.all([fetchUser(), fetchPosts(), fetchComments()])
.then(([user, posts, comments]) => {
console.log('All data loaded:', user, posts, comments);
});
// 竞速:第一个完成的结果
Promise.race([fastApi(), slowApi()])
.then(result => console.log('First result:', result));
六、模块化:大型应用的基石
9. ES6 模块
javascript
// math.js - 导出模块
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
// 默认导出(每个模块一个)
export default class Calculator {
// ...
}
// app.js - 导入模块
import Calculator, { PI, add } from './math.js';
import * as MathUtils from './math.js'; // 全部导入
const calc = new Calculator();
console.log(add(2, 3)); // 5
七、类与面向对象
10. Class 语法糖
javascript
// 传统构造函数方式
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log('Hello, ' + this.name);
};
// ES6 Class 方式
class Person {
constructor(name) {
this.name = name;
}
// 实例方法
greet() {
console.log(`Hello, ${this.name}!`);
}
// 静态方法
static createAnonymous() {
return new Person('Anonymous');
}
}
// 继承
class Student extends Person {
constructor(name, grade) {
super(name); // 必须首先调用 super()
this.grade = grade;
}
study() {
console.log(`${this.name} is studying for grade ${this.grade}`);
}
// 重写父类方法
greet() {
super.greet(); // 调用父类方法
console.log(`I'm in grade ${this.grade}`);
}
}
// 使用
const student = new Student('Alice', 'A');
student.greet();
student.study();
八、新数据结构:Set 与 Map
11. Set:唯一值集合
javascript
数组去重(经典用例) const numbers = [1, 2, 2, 3, 4, 4, 5]; const uniqueNumbers = [...new Set(numbers)]; // [1, 2, 3, 4, 5] // Set 操作 const tags = new Set(['js', 'html', 'css']); tags.add('react'); tags.add('js'); // 重复添加,无效果 tags.delete('html'); tags.has('css'); // true tags.size; // 3 // 遍历 for (const tag of tags) { console.log(tag); }
12. Map:键值对集合
javascript
// 与普通对象的区别:Map 的键可以是任何类型
const map = new Map();
// 对象作为键
const objKey = { id: 1 };
const funcKey = function() {};
map.set(objKey, 'value for object');
map.set(funcKey, 'value for function');
map.set('stringKey', 'value for string');
map.get(objKey); // 'value for object'
// 实用的数据存储
const userSessions = new Map();
function login(userId, sessionData) {
userSessions.set(userId, {
...sessionData,
loginTime: new Date()
});
}
function getSession(userId) {
return userSessions.get(userId);
}
九、其他实用特性
13. 迭代器与生成器
javascript
// 自定义可迭代对象
const countdown = {
from: 3,
to: 1,
[Symbol.iterator]() {
let current = this.from;
const last = this.to;
return {
next() {
if (current >= last) {
return { value: current--, done: false };
} else {
return { done: true };
}
}
};
}
};
for (let num of countdown) {
console.log(num); // 3, 2, 1
}
// 生成器函数:懒加载数据
function* fetchPages(url) {
let page = 1;
while (true) {
const response = yield fetch(`${url}?page=${page}`);
if (response.status === 404) break;
page++;
}
}
14. 实用方法增强
javascript
// 字符串检查
const str = 'Hello world';
str.includes('world'); // true
str.startsWith('Hello'); // true
str.endsWith('world'); // true
// 数组方法
const arr = [1, 2, 3, 4, 5];
arr.includes(3); // true
arr.find(n => n > 3); // 4
arr.findIndex(n => n > 3); // 3
总结与学习建议
ES6 不仅仅是新语法,更是一种新的思维方式。这些特性共同作用,让 JavaScript 开发变得更加:
-
安全可靠 :
let/const避免意外错误 -
简洁优雅:箭头函数、解构、模板字符串减少样板代码
-
表达力强:类、模块让代码组织更清晰
-
异步友好 :Promise 为
async/await(ES2017)奠定基础