ES6 (ECMAScript 2015) 新特性全解析
引言
ES6,正式名称为ECMAScript 2015,是JavaScript语言的一次重大更新,引入了许多新特性和语法改进,极大地提升了代码的可读性、可维护性和开发效率。本文将详细介绍ES6中最常用的核心特性。
1. 块级作用域声明: let 和 const
ES6引入了let和const关键字,解决了var声明的变量提升和作用域问题。
let 声明
- 具有块级作用域,只在声明的代码块内有效
- 不存在变量提升,必须先声明后使用
- 同一作用域内不允许重复声明
// var声明的问题
if (true) {
var a = 10;
}
console.log(a); // 10 (变量提升到全局作用域)
// let声明的优势
if (true) {
let b = 20;
console.log(b); // 20
}
console.log(b); // ReferenceError: b is not defined
const 声明
- 用于声明常量,一旦声明,值不能改变
- 同样具有块级作用域
- 声明时必须初始化
const PI = 3.1415926;
PI = 3.14; // TypeError: Assignment to constant variable
// 注意:对象属性可以修改
const person = {
name: 'John'
};
person.name = 'Jane'; // 允许
person = {}; // TypeError: Assignment to constant variable
2. 箭头函数 (Arrow Functions)
箭头函数提供了更简洁的函数语法,并且绑定了词法作用域的this值。
基本语法
// 传统函数
function add(a, b) {
return a + b;
}
// 箭头函数
const add = (a, b) => a + b;
// 多行函数体需要大括号和return
const multiply = (a, b) => {
const result = a * b;
return result;
};
// 单个参数可以省略括号
const square = x => x * x;
词法 this 绑定
箭头函数没有自己的this,它会捕获所在上下文的this值。
// 传统函数中的this问题
const obj = {
name: 'Arrow Function',
timer: function() {
setTimeout(function() {
console.log(this.name); // undefined (this指向全局对象)
}, 1000);
}
};
// 使用箭头函数解决
const obj = {
name: 'Arrow Function',
timer: function() {
setTimeout(() => {
console.log(this.name); // Arrow Function (this继承自timer函数)
}, 1000);
}
};
3. 模板字符串 (Template Strings)
使用反引号(`)创建字符串,支持多行文本和表达式嵌入。
基本用法
// 多行字符串
const multiLine = `这是第一行
这是第二行
这是第三行`;
// 表达式嵌入
const name = 'John';
const age = 30;
const greeting = `Hello, my name is ${name} and I'm ${age} years old.`;
// 表达式计算
const a = 10;
const b = 20;
const result = `The sum of ${a} and ${b} is ${a + b}`; // "The sum of 10 and 20 is 30"
4. 解构赋值 (Destructuring Assignment)
允许从数组或对象中提取值,并赋给变量。
数组解构
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
// 默认值
const [x, y = 10] = [5];
console.log(x); // 5
console.log(y); // 10
对象解构
const person = {
name: 'John',
age: 30,
address: {
city: 'New York'
}
};
// 基本对象解构
const { name, age } = person;
console.log(name); // John
console.log(age); // 30
// 重命名变量
const { name: personName } = person;
console.log(personName); // John
// 嵌套解构
const { address: { city } } = person;
console.log(city); // New York
5. 默认参数 (Default Parameters)
允许为函数参数设置默认值。
// 基本用法
function greet(name = 'Guest') {
return `Hello, ${name}!`;
}
console.log(greet()); // Hello, Guest!
console.log(greet('John')); // Hello, John!
// 复杂表达式作为默认值
function fetchData(url, timeout = 5000, callback = () => console.log('Done')) {
// ...
}
6. 扩展运算符 (Spread Operator)
使用...语法,可将数组或对象展开为多个元素。
数组扩展
// 数组复制
const original = [1, 2, 3];
const copy = [...original];
// 数组合并
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// 函数参数
const numbers = [1, 2, 3];
const sum = (a, b, c) => a + b + c;
console.log(sum(...numbers)); // 6
对象扩展
// 对象复制
const obj = { a: 1, b: 2 };
const objCopy = { ...obj };
// 对象合并
const obj1 = { a: 1 };
const obj2 = { b: 2 };
const mergedObj = { ...obj1, ...obj2 }; // { a: 1, b: 2 }
// 覆盖属性
const obj3 = { a: 1, b: 2 };
const obj4 = { b: 3, c: 4 };
const mergedObj2 = { ...obj3, ...obj4 }; // { a: 1, b: 3, c: 4 }
7. 类 (Class)
ES6引入了class语法糖,使面向对象编程更加清晰。
// 类定义
class Person {
// 构造函数
constructor(name, age) {
this.name = name;
this.age = age;
}
// 实例方法
greet() {
return `Hello, my name is ${this.name}`;
}
// 静态方法
static createPerson(name, age) {
return new Person(name, age);
}
// getter
get birthYear() {
return new Date().getFullYear() - this.age;
}
}
// 类继承
class Student extends Person {
constructor(name, age, major) {
super(name, age); // 调用父类构造函数
this.major = major;
}
// 重写父类方法
greet() {
return `${super.greet()} and I'm studying ${this.major}`;
}
}
// 使用类
const student = new Student('John', 20, 'Computer Science');
console.log(student.greet()); // Hello, my name is John and I'm studying Computer Science
console.log(student.birthYear); // 2003 (根据当前年份计算)
8. 模块系统 (Modules)
ES6引入了原生模块系统,使用import和export关键字。
导出 (Export)
// math.js
// 命名导出
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
// 默认导出
export default function multiply(a, b) {
return a * b;
}
导入 (Import)
// app.js
// 导入默认导出
import multiply from './math.js';
// 导入命名导出
import { add, subtract } from './math.js';
// 导入所有命名导出
import * as MathUtils from './math.js';
console.log(multiply(2, 3)); // 6
console.log(add(2, 3)); // 5
console.log(MathUtils.subtract(5, 2)); // 3
9. Promise
Promise用于处理异步操作,避免回调地狱。
基本用法
// 创建Promise
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve('Data fetched successfully');
} else {
reject(new Error('Failed to fetch data'));
}
}, 1000);
});
};
// 使用Promise
fetchData()
.then(data => {
console.log(data); // Data fetched successfully
return data.toUpperCase();
})
.then(uppercaseData => {
console.log(uppercaseData); // DATA FETCHED SUCCESSFULLY
})
.catch(error => {
console.error(error.message);
})
.finally(() => {
console.log('Operation completed');
});
10. Map 和 Set
ES6引入了两种新的数据结构:Map和Set。
Map
键值对集合,键可以是任意类型。
const map = new Map();
map.set('name', 'John');
map.set(1, 'Number one');
map.set(true, 'Boolean true');
console.log(map.get('name')); // John
console.log(map.size); // 3
console.log(map.has('name')); // true
// 遍历Map
map.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
Set
唯一值的集合,不允许重复元素。
const set = new Set([1, 2, 3, 3, 4]);
console.log(set.size); // 4 (自动去重)
console.log(set.has(3)); // true
set.add(5);
set.delete(1);
// 遍历Set
for (const value of set) {
console.log(value); // 2, 3, 4, 5
}
// 转换为数组
const arr = Array.from(set); // [2, 3, 4, 5]
11. 其他重要特性
for...of 循环
用于遍历可迭代对象(数组、Map、Set等)。
const arr = [1, 2, 3];
for (const value of arr) {
console.log(value); // 1, 2, 3
}
const map = new Map([['a', 1], ['b', 2]]);
for (const [key, value] of map) {
console.log(`${key}: ${value}`); // a: 1, b: 2
}
Symbol
创建唯一标识符,用于对象属性名,避免属性名冲突。
const sym1 = Symbol('description');
const sym2 = Symbol('description');
console.log(sym1 === sym2); // false (每个Symbol都是唯一的)
const obj = {
[sym1]: 'value'
};
console.log(obj[sym1]); // value
函数参数的剩余参数 (Rest Parameters)
收集函数的剩余参数为数组。
function sum(...numbers) {
return numbers.reduce((acc, curr) => acc + curr, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
总结
ES6为JavaScript带来了许多强大的新特性,极大地改善了开发体验。本文介绍的只是其中最常用的一部分,还有许多其他特性如Proxy、Reflect、Generator等也值得深入学习。掌握这些新特性,能够帮助我们编写更简洁、高效、可维护的JavaScript代码。
随着JavaScript的不断发展,每年都会有新的特性加入。建议保持学习,跟上语言发展的步伐,充分利用新特性提升开发效率。