Skip to content

ES6 新特性

ES6(ECMAScript 2015)是 JavaScript 语言的一个重要更新,引入了许多新特性和语法改进,使 JavaScript 更加强大和易用。这些新特性大大提升了开发体验和代码质量。

let 和 const

ES6 引入了两个新的变量声明关键字:letconst,它们提供了块级作用域。

javascript
// var 的函数作用域
function varExample() {
    if (true) {
        var x = 1;
    }
    console.log(x); // 1 (可以访问)
}

// let 的块级作用域
function letExample() {
    if (true) {
        let y = 1;
    }
    // console.log(y); // ReferenceError: y is not defined
}

// const 声明常量
const PI = 3.14159;
// PI = 3.14; // TypeError: Assignment to constant variable

// const 对象和数组
const person = { name: "张三" };
person.name = "李四"; // 可以修改属性
person.age = 25;      // 可以添加属性
// person = {};        // TypeError: Assignment to constant variable

const numbers = [1, 2, 3];
numbers.push(4);      // 可以修改数组内容
// numbers = [5, 6, 7]; // TypeError: Assignment to constant variable

模板字符串

模板字符串使用反引号(`)包围,支持多行字符串和字符串插值。

javascript
// 基本用法
let name = "张三";
let greeting = `你好,${name}!`;
console.log(greeting); // "你好,张三!"

// 多行字符串
let multiline = `
这是第一行
这是第二行
这是第三行
`;

// 表达式插值
let a = 5;
let b = 10;
console.log(`a + b = ${a + b}`); // "a + b = 15"

// 嵌套模板字符串
let users = [
    { name: "张三", age: 25 },
    { name: "李四", age: 30 }
];

let userList = `
<ul>
  ${users.map(user => `<li>${user.name} (${user.age}岁)</li>`).join('\n  ')}
</ul>
`;

解构赋值

解构赋值允许我们从数组或对象中提取值并赋给变量。

javascript
// 数组解构
let [first, second, third] = [1, 2, 3];
console.log(first);  // 1
console.log(second); // 2
console.log(third);  // 3

// 跳过某些值
let [a, , c] = [1, 2, 3];
console.log(a); // 1
console.log(c); // 3

// 默认值
let [x = 10, y = 20] = [5];
console.log(x); // 5
console.log(y); // 20

// 对象解构
let person = { name: "张三", age: 25, city: "北京" };
let { name, age } = person;
console.log(name); // "张三"
console.log(age);  // 25

// 重命名变量
let { name: fullName, age: years } = person;
console.log(fullName); // "张三"
console.log(years);    // 25

// 默认值
let { name: n, job = "开发者" } = person;
console.log(n);  // "张三"
console.log(job); // "开发者"

// 嵌套解构
let student = {
    name: "李四",
    address: {
        city: "上海",
        district: "浦东新区"
    }
};

let { address: { city } } = student;
console.log(city); // "上海"

扩展运算符

扩展运算符(...)允许我们在函数调用/数组构造时将数组表达式或字符串在语法层面展开。

javascript
// 数组展开
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]

// 复制数组
let original = [1, 2, 3];
let copy = [...original];
console.log(copy); // [1, 2, 3]
copy.push(4);
console.log(original); // [1, 2, 3] (原数组未改变)
console.log(copy);     // [1, 2, 3, 4]

// 字符串展开
let str = "hello";
let chars = [...str];
console.log(chars); // ['h', 'e', 'l', 'l', 'o']

// 对象展开(ES2018)
let obj1 = { a: 1, b: 2 };
let obj2 = { c: 3, d: 4 };
let merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 2, c: 3, d: 4 }

// 复制对象
let originalObj = { name: "张三", age: 25 };
let copyObj = { ...originalObj };
console.log(copyObj); // { name: "张三", age: 25 }

// 合并对象并覆盖属性
let defaults = { theme: "light", lang: "zh" };
let userPrefs = { lang: "en", notifications: true };
let settings = { ...defaults, ...userPrefs };
console.log(settings); // { theme: "light", lang: "en", notifications: true }

箭头函数

箭头函数提供了一种更简洁的函数书写方式,并且不绑定自己的 this。

javascript
// 基本语法
let add = (a, b) => a + b;
console.log(add(2, 3)); // 5

// 单参数可以省略括号
let double = x => x * 2;
console.log(double(5)); // 10

// 多行函数体需要大括号和 return
let multiply = (a, b) => {
    let result = a * b;
    return result;
};
console.log(multiply(3, 4)); // 12

// 无参数
let greet = () => "Hello!";
console.log(greet()); // "Hello!"

// 返回对象字面量需要加括号
let createUser = (name, age) => ({ name, age });
console.log(createUser("张三", 25)); // { name: "张三", age: 25 }

// 箭头函数中的 this
let obj = {
    name: "对象",
    regularFunction: function() {
        console.log("常规函数:", this.name);
        
        // 箭头函数继承外层的 this
        let arrow = () => {
            console.log("箭头函数:", this.name);
        };
        arrow();
    }
};

obj.regularFunction();
// 输出:
// 常规函数: 对象
// 箭头函数: 对象

类(Class)

ES6 引入了类语法,提供了一种更清晰的面向对象编程方式。

javascript
// 基本类定义
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    
    greet() {
        return `你好,我是 ${this.name},今年 ${this.age} 岁。`;
    }
    
    // 静态方法
    static getSpecies() {
        return "人类";
    }
}

let person = new Person("张三", 25);
console.log(person.greet()); // "你好,我是 张三,今年 25 岁。"
console.log(Person.getSpecies()); // "人类"

// 类继承
class Student extends Person {
    constructor(name, age, school) {
        super(name, age); // 调用父类构造函数
        this.school = school;
    }
    
    // 方法重写
    greet() {
        return `${super.greet()} 我在 ${this.school} 学习。`;
    }
    
    study() {
        return `${this.name} 正在学习。`;
    }
}

let student = new Student("李四", 20, "北京大学");
console.log(student.greet()); // "你好,我是 李四,今年 20 岁。 我在 北京大学 学习。"
console.log(student.study()); // "李四 正在学习。"

// Getter 和 Setter
class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }
    
    get area() {
        return this.width * this.height;
    }
    
    set area(value) {
        // 这里简化处理,实际可能需要更复杂的逻辑
        this.width = Math.sqrt(value);
        this.height = Math.sqrt(value);
    }
}

let rect = new Rectangle(5, 3);
console.log(rect.area); // 15
rect.area = 25;
console.log(rect.width);  // 5
console.log(rect.height); // 5

模块(Modules)

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 function subtract(a, b) {
    return a - b;
}

// 可以在文件末尾统一导出
export { add as sum, multiply as product };

// main.js - 导入模块
import subtract, { PI, add, multiply as mul, sum } from './math.js';

console.log(PI);        // 3.14159
console.log(add(2, 3)); // 5
console.log(mul(2, 3)); // 6
console.log(subtract(5, 2)); // 3

Promise

Promise 提供了更好的异步编程方式。

javascript
// 创建 Promise
let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        let success = true;
        if (success) {
            resolve("操作成功!");
        } else {
            reject("操作失败!");
        }
    }, 1000);
});

// 使用 Promise
promise
    .then(result => {
        console.log(result); // "操作成功!"
    })
    .catch(error => {
        console.error(error); // "操作失败!"
    });

// Promise 静态方法
Promise.all([
    fetch('/api/data1'),
    fetch('/api/data2')
]).then(responses => {
    console.log("所有请求完成");
});

Promise.race([
    fetch('/api/data1'),
    fetch('/api/data2')
]).then(response => {
    console.log("第一个完成的请求");
});

其他有用特性

默认参数

javascript
function greet(name = "朋友", greeting = "你好") {
    return `${greeting},${name}!`;
}

console.log(greet());           // "你好,朋友!"
console.log(greet("张三"));      // "你好,张三!"
console.log(greet("李四", "欢迎")); // "欢迎,李四!"

剩余参数

javascript
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3));        // 6
console.log(sum(1, 2, 3, 4, 5));  // 15

// 与解构赋值结合使用
let [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest);  // [2, 3, 4, 5]

for...of 循环

javascript
let fruits = ["苹果", "香蕉", "橙子"];

// 遍历数组元素
for (let fruit of fruits) {
    console.log(fruit);
}

// 遍历字符串
let str = "hello";
for (let char of str) {
    console.log(char);
}

// 遍历 Map
let map = new Map([["a", 1], ["b", 2]]);
for (let [key, value] of map) {
    console.log(key, value);
}

ES6 的这些新特性使 JavaScript 更加强大和易用,提升了代码的可读性和可维护性。掌握这些特性对于现代 JavaScript 开发至关重要。