ES6 (ECMAScript 2015) 详解速览

ES6 (ECMAScript 2015) 详解速览

1. ES6 概述

ES6(ECMAScript 2015)是 JavaScript 语言的一个重要版本,引入了许多新特性和语法糖,让 JavaScript 更加强大和易用。

主要改进:

  • 语法增强:更简洁的语法
  • 模块化:原生支持模块化开发
  • 面向对象:更好的类和继承支持
  • 异步编程:Promise 和 Generator
  • 数据结构:新的数据类型和集合

2. 变量声明

2.1 let 和 const

// let 块级作用域
{
    let x = 1;
    var y = 2;
}
// console.log(x); // ReferenceError: x is not defined
console.log(y); // 2

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

// 对象和数组的 const
const obj = { name: 'John' };
obj.name = 'Jane'; // 可以修改属性
obj.age = 25; // 可以添加属性
// obj = {}; // TypeError: Assignment to constant variable

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

2.2 变量提升差异

// var 变量提升
console.log(a); // undefined
var a = 1;

// let 暂时性死区
// console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 2;

// 循环中的差异
for (var i = 0; i < 3; i++) {
    setTimeout(() => console.log('var:', i), 100); // 输出 3, 3, 3
}

for (let j = 0; j < 3; j++) {
    setTimeout(() => console.log('let:', j), 100); // 输出 0, 1, 2
}

3. 解构赋值

3.1 数组解构

// 基本解构
const [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1 2 3

// 跳过元素
const [first, , third] = [1, 2, 3, 4];
console.log(first, third); // 1 3

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

// 嵌套解构
const [p, [q, r]] = [1, [2, 3]];
console.log(p, q, r); // 1 2 3

// 剩余元素
const [head, ...tail] = [1, 2, 3, 4];
console.log(head, tail); // 1 [2, 3, 4]

3.2 对象解构

// 基本解构
const person = { name: 'John', age: 30, city: 'New York' };
const { name, age } = person;
console.log(name, age); // John 30

// 重命名
const { name: fullName, age: years } = person;
console.log(fullName, years); // John 30

// 默认值
const { name: n, gender = 'unknown' } = person;
console.log(n, gender); // John unknown

// 嵌套解构
const user = {
    name: 'Alice',
    address: {
        street: '123 Main St',
        city: 'Boston'
    }
};
const { address: { city } } = user;
console.log(city); // Boston

// 函数参数解构
function greet({ name, greeting = 'Hello' }) {
    return `${greeting}, ${name}!`;
}
console.log(greet({ name: 'Bob' })); // Hello, Bob!

4. 字符串扩展

4.1 模板字符串

// 基本模板字符串
const name = 'John';
const age = 30;
const message = `Hello, ${name}! You are ${age} years old.`;
console.log(message); // Hello, John! You are 30 years old.

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

// 表达式
const price = 100;
const tax = 0.08;
const total = `Total: $${(price * (1 + tax)).toFixed(2)}`;
console.log(total); // Total: $108.00

// 标签模板
function highlight(strings, ...values) {
    return strings.reduce((result, string, i) => {
        return result + string + (values[i] ? `<mark>${values[i]}</mark>` : '');
    }, '');
}

const name2 = 'Alice';
const age2 = 25;
const result = highlight`Hello, ${name2}! You are ${age2} years old.`;
console.log(result); // Hello, <mark>Alice</mark>! You are <mark>25</mark> years old.

4.2 字符串新方法

// includes()
console.log('hello world'.includes('world')); // true
console.log('hello world'.includes('World')); // false

// startsWith()
console.log('hello world'.startsWith('hello')); // true
console.log('hello world'.startsWith('world', 6)); // true

// endsWith()
console.log('hello world'.endsWith('world')); // true
console.log('hello world'.endsWith('hello', 5)); // true

// repeat()
console.log('abc'.repeat(3)); // abcabcabc

// padStart() 和 padEnd()
console.log('5'.padStart(2, '0')); // 05
console.log('5'.padEnd(3, '0')); // 500

5. 函数扩展

5.1 默认参数

// 基本默认参数
function greet(name = 'Guest', greeting = 'Hello') {
    return `${greeting}, ${name}!`;
}

console.log(greet()); // Hello, Guest!
console.log(greet('John')); // Hello, John!
console.log(greet('Alice', 'Hi')); // Hi, Alice!

// 表达式作为默认值
function add(x, y = x) {
    return x + y;
}
console.log(add(5)); // 10
console.log(add(5, 3)); // 8

// 函数作为默认值
function required() {
    throw new Error('Parameter is required');
}

function multiply(a = required(), b = 1) {
    return a * b;
}
// multiply(); // Error: Parameter is required

5.2 剩余参数

// 基本剩余参数
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15

// 与普通参数结合
function multiply(multiplier, ...numbers) {
    return numbers.map(num => num * multiplier);
}
console.log(multiply(2, 1, 2, 3)); // [2, 4, 6]

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

5.3 箭头函数

// 基本语法
const add = (a, b) => a + b;
const square = x => x * x;
const greet = () => 'Hello!';

// 返回对象字面量
const createPerson = (name, age) => ({ name, age });

// 单参数可以省略括号
const double = x => x * 2;

// 多行箭头函数
const processArray = arr => {
    const filtered = arr.filter(x => x > 0);
    const doubled = filtered.map(x => x * 2);
    return doubled.reduce((sum, x) => sum + x, 0);
};

// this 绑定差异
const obj = {
    name: 'John',
    regularFunction: function() {
        setTimeout(function() {
            console.log(this.name); // undefined
        }, 100);
    },
    arrowFunction: function() {
        setTimeout(() => {
            console.log(this.name); // John
        }, 100);
    }
};

6. 对象扩展

6.1 属性简写

// 属性简写
const name = 'John';
const age = 30;
const person = { name, age }; // 等同于 { name: name, age: age }
console.log(person); // { name: 'John', age: 30 }

// 方法简写
const calculator = {
    add(a, b) { return a + b; },
    subtract(a, b) { return a - b; },
    multiply(a, b) { return a * b; }
};

// 计算属性名
const prefix = 'user_';
const obj = {
    [prefix + 'name']: 'John',
    [prefix + 'age']: 30,
    [`${prefix}id`]: 123
};
console.log(obj); // { user_name: 'John', user_age: 30, userid: 123 }

6.2 对象方法

// Object.assign()
const target = { a: 1, b: 2 };
const source1 = { b: 4, c: 5 };
const source2 = { c: 6, d: 7 };
const result = Object.assign(target, source1, source2);
console.log(result); // { a: 1, b: 4, c: 6, d: 7 }

// Object.keys(), Object.values(), Object.entries()
const obj2 = { a: 1, b: 2, c: 3 };
console.log(Object.keys(obj2)); // ['a', 'b', 'c']
console.log(Object.values(obj2)); // [1, 2, 3]
console.log(Object.entries(obj2)); // [['a', 1], ['b', 2], ['c', 3]]

// 对象遍历
for (const [key, value] of Object.entries(obj2)) {
    console.log(`${key}: ${value}`);
}

7. 数组扩展

7.1 新的数组方法

// Array.from()
console.log(Array.from('hello')); // ['h', 'e', 'l', 'l', 'o']
console.log(Array.from({ length: 3 }, (v, i) => i)); // [0, 1, 2]

// Array.of()
console.log(Array.of(1, 2, 3)); // [1, 2, 3]
console.log(Array.of(3)); // [3] vs new Array(3) // [empty × 3]

// find() 和 findIndex()
const numbers = [1, 2, 3, 4, 5];
const found = numbers.find(x => x > 3);
console.log(found); // 4

const index = numbers.findIndex(x => x > 3);
console.log(index); // 3

// includes()
console.log([1, 2, 3].includes(2)); // true
console.log([1, 2, 3].includes(4)); // false

// flat() 和 flatMap()
const nested = [1, [2, 3], [4, [5, 6]]];
console.log(nested.flat()); // [1, 2, 3, 4, [5, 6]]
console.log(nested.flat(2)); // [1, 2, 3, 4, 5, 6]

const arr = [1, 2, 3];
console.log(arr.flatMap(x => [x, x * 2])); // [1, 2, 2, 4, 3, 6]

7.2 数组解构和扩展

// 数组复制
const original = [1, 2, 3];
const copy = [...original];
const extended = [...original, 4, 5];

// 数组合并
const arr1 = [1, 2];
const arr2 = [3, 4];
const merged = [...arr1, ...arr2]; // [1, 2, 3, 4]

// 将类数组对象转换为数组
function example() {
    const args = Array.from(arguments);
    // 或者 const args = [...arguments]; // 仅在函数内部可用
    return args;
}

8. 类 (Class)

8.1 基本类定义

// 基本类
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    
    // 方法
    greet() {
        return `Hello, I'm ${this.name}`;
    }
    
    // getter 和 setter
    get description() {
        return `${this.name} is ${this.age} years old`;
    }
    
    set nickname(value) {
        this._nickname = value;
    }
    
    get nickname() {
        return this._nickname || this.name;
    }
    
    // 静态方法
    static compareAge(person1, person2) {
        return person1.age - person2.age;
    }
}

const john = new Person('John', 30);
console.log(john.greet()); // Hello, I'm John
console.log(john.description); // John is 30 years old
john.nickname = 'Johnny';
console.log(john.nickname); // Johnny

const alice = new Person('Alice', 25);
console.log(Person.compareAge(john, alice)); // 5

8.2 继承

// 继承
class Employee extends Person {
    constructor(name, age, salary) {
        super(name, age); // 调用父类构造函数
        this.salary = salary;
    }
    
    // 重写方法
    greet() {
        return `${super.greet()} and I earn $${this.salary}`;
    }
    
    // 新方法
    work() {
        return `${this.name} is working`;
    }
    
    // 静态方法继承
    static createEmployee(name, age, salary) {
        return new Employee(name, age, salary);
    }
}

const emp = new Employee('Bob', 35, 50000);
console.log(emp.greet()); // Hello, I'm Bob and I earn $50000
console.log(emp.work()); // Bob is working

const emp2 = Employee.createEmployee('Charlie', 28, 45000);
console.log(emp2 instanceof Employee); // true
console.log(emp2 instanceof Person); // true

9. 模块化

9.1 导出 (Export)

// math.js
// 命名导出
export const PI = 3.14159;
export function add(a, b) {
    return a + b;
}
export function subtract(a, b) {
    return a - b;
}

// 默认导出
export default function multiply(a, b) {
    return a * b;
}

// 或者单独导出默认
// export default class Calculator { ... }

// 批量导出
const MAX_VALUE = 1000;
const MIN_VALUE = 0;
export { MAX_VALUE, MIN_VALUE };

9.2 导入 (Import)

// main.js
// 导入命名导出
import { PI, add, subtract } from './math.js';
console.log(PI); // 3.14159
console.log(add(2, 3)); // 5

// 导入默认导出
import multiply from './math.js';
console.log(multiply(4, 5)); // 20

// 导入所有
import * as MathUtils from './math.js';
console.log(MathUtils.PI);
console.log(MathUtils.add(1, 2));

// 重命名导入
import { add as sum, subtract as minus } from './math.js';
console.log(sum(5, 3)); // 8

// 混合导入
import multiply, { PI, add } from './math.js';

10. Promise

10.1 基本 Promise

// 创建 Promise
const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        const success = Math.random() > 0.5;
        if (success) {
            resolve('Operation successful!');
        } else {
            reject(new Error('Operation failed!'));
        }
    }, 1000);
});

// 使用 Promise
promise
    .then(result => {
        console.log(result);
        return result.toUpperCase();
    })
    .then(upperResult => {
        console.log(upperResult);
    })
    .catch(error => {
        console.error('Error:', error.message);
    })
    .finally(() => {
        console.log('Operation completed');
    });

10.2 Promise 静态方法

// Promise.resolve()
const resolvedPromise = Promise.resolve('Success');
resolvedPromise.then(console.log); // Success

// Promise.reject()
const rejectedPromise = Promise.reject(new Error('Failed'));
rejectedPromise.catch(error => console.error(error.message)); // Failed

// Promise.all()
const promises = [
    Promise.resolve(1),
    Promise.resolve(2),
    Promise.resolve(3)
];

Promise.all(promises)
    .then(results => console.log(results)) // [1, 2, 3]
    .catch(error => console.error(error));

// Promise.race()
const promise1 = new Promise(resolve => setTimeout(() => resolve('First'), 100));
const promise2 = new Promise(resolve => setTimeout(() => resolve('Second'), 200));

Promise.race([promise1, promise2])
    .then(result => console.log(result)); // First

// Promise.allSettled()
const mixedPromises = [
    Promise.resolve('Success'),
    Promise.reject(new Error('Failed')),
    Promise.resolve('Another success')
];

Promise.allSettled(mixedPromises)
    .then(results => {
        results.forEach((result, index) => {
            if (result.status === 'fulfilled') {
                console.log(`Promise ${index}: ${result.value}`);
            } else {
                console.log(`Promise ${index}: ${result.reason.message}`);
            }
        });
    });

11. 异步函数 (Async/Await)

11.1 基本用法

// 异步函数
async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        return data;
    } catch (error) {
        console.error('Error fetching data:', error);
        throw error;
    }
}

// 使用异步函数
fetchData()
    .then(data => console.log(data))
    .catch(error => console.error(error));

// 在另一个异步函数中使用
async function processData() {
    try {
        const data = await fetchData();
        const processed = data.map(item => item.name);
        return processed;
    } catch (error) {
        console.error('Error processing data:', error);
        return [];
    }
}

11.2 并行执行

// 并行执行多个异步操作
async function fetchMultipleData() {
    try {
        // 并行执行
        const [users, posts, comments] = await Promise.all([
            fetch('/api/users').then(r => r.json()),
            fetch('/api/posts').then(r => r.json()),
            fetch('/api/comments').then(r => r.json())
        ]);
        
        return { users, posts, comments };
    } catch (error) {
        console.error('Error fetching data:', error);
        throw error;
    }
}

// 串行执行
async function fetchSequentialData() {
    try {
        const users = await fetch('/api/users').then(r => r.json());
        const posts = await fetch('/api/posts').then(r => r.json());
        const comments = await fetch('/api/comments').then(r => r.json());
        
        return { users, posts, comments };
    } catch (error) {
        console.error('Error fetching data:', error);
        throw error;
    }
}

12. 生成器 (Generator)

12.1 基本生成器

// 生成器函数
function* countUp() {
    let index = 0;
    while (index < 3) {
        yield index++;
    }
}

const counter = countUp();
console.log(counter.next()); // { value: 0, done: false }
console.log(counter.next()); // { value: 1, done: false }
console.log(counter.next()); // { value: 2, done: false }
console.log(counter.next()); // { value: undefined, done: true }

// 使用 for...of 遍历生成器
function* range(start, end) {
    for (let i = start; i <= end; i++) {
        yield i;
    }
}

for (const num of range(1, 5)) {
    console.log(num); // 1, 2, 3, 4, 5
}

12.2 生成器与异步

// 异步生成器
async function* asyncRange(start, end) {
    for (let i = start; i <= end; i++) {
        await new Promise(resolve => setTimeout(resolve, 1000));
        yield i;
    }
}

// 使用异步生成器
async function printAsyncRange() {
    for await (const num of asyncRange(1, 3)) {
        console.log(num);
    }
}

13. 新的数据结构

13.1 Set

// Set 基本用法
const set = new Set([1, 2, 3, 2, 1]);
console.log(set); // Set { 1, 2, 3 }

// Set 方法
set.add(4);
set.add(4); // 重复添加无效
console.log(set.has(2)); // true
console.log(set.size); // 4
set.delete(2);
console.log(set); // Set { 1, 3, 4 }

// 遍历 Set
for (const item of set) {
    console.log(item);
}

set.forEach(item => console.log(item));

// 数组去重
const uniqueArray = [...new Set([1, 2, 2, 3, 3, 4])];
console.log(uniqueArray); // [1, 2, 3, 4]

13.2 Map

// Map 基本用法
const map = new Map();
map.set('name', 'John');
map.set('age', 30);
map.set(1, 'number one');

console.log(map.get('name')); // John
console.log(map.has('age')); // true
console.log(map.size); // 3

// 使用对象作为键
const user1 = { id: 1 };
const user2 = { id: 2 };
const userMap = new Map();
userMap.set(user1, 'John');
userMap.set(user2, 'Jane');

console.log(userMap.get(user1)); // John

// 遍历 Map
for (const [key, value] of map) {
    console.log(key, value);
}

map.forEach((value, key) => {
    console.log(key, value);
});

13.3 WeakMap 和 WeakSet

// WeakMap
const wm = new WeakMap();
const obj = {};
wm.set(obj, 'value');
console.log(wm.get(obj)); // value

// WeakSet
const ws = new WeakSet();
const obj2 = {};
ws.add(obj2);
console.log(ws.has(obj2)); // true

// WeakMap 和 WeakSet 不会阻止垃圾回收

14. Symbol

14.1 Symbol 基本用法

// 创建 Symbol
const sym1 = Symbol();
const sym2 = Symbol('description');
const sym3 = Symbol('description');

console.log(sym1 === sym2); // false
console.log(sym2 === sym3); // false

// Symbol 作为对象属性
const obj = {
    [sym1]: 'value1',
    [sym2]: 'value2'
};

console.log(obj[sym1]); // value1
console.log(Object.keys(obj)); // []
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(), Symbol(description)]

// 全局 Symbol 注册表
const globalSym = Symbol.for('global');
const anotherGlobalSym = Symbol.for('global');
console.log(globalSym === anotherGlobalSym); // true

// 获取 Symbol 的键
console.log(Symbol.keyFor(globalSym)); // 'global'

14.2 内置 Symbol

// Symbol.iterator
const iterable = {
    *[Symbol.iterator]() {
        yield 1;
        yield 2;
        yield 3;
    }
};

for (const value of iterable) {
    console.log(value); // 1, 2, 3
}

// Symbol.toStringTag
class MyClass {
    get [Symbol.toStringTag]() {
        return 'MyClass';
    }
}

const obj = new MyClass();
console.log(Object.prototype.toString.call(obj)); // [object MyClass]

15. 实用示例

15.1 数据处理管道

// 函数式编程管道
const pipe = (...fns) => (value) => fns.reduce((acc, fn) => fn(acc), value);

const add = (x) => (y) => x + y;
const multiply = (x) => (y) => x * y;
const square = (x) => x * x;

const processNumber = pipe(
    add(5),
    multiply(2),
    square
);

console.log(processNumber(3)); // ((3 + 5) * 2)² = 256

15.2 模块化应用结构

// api.js
export class ApiService {
    async get(url) {
        const response = await fetch(url);
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.json();
    }
}

// utils.js
export const formatDate = (date) => {
    return new Intl.DateTimeFormat('en-US').format(date);
};

export const debounce = (func, wait) => {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
};

// main.js
import { ApiService } from './api.js';
import { formatDate, debounce } from './utils.js';

const api = new ApiService();

class App {
    constructor() {
        this.init();
    }
    
    async init() {
        try {
            const data = await api.get('/api/data');
            this.render(data);
        } catch (error) {
            console.error('Failed to load data:', error);
        }
    }
    
    render(data) {
        const formattedDate = formatDate(new Date());
        console.log(`Data loaded at: ${formattedDate}`, data);
    }
}

new App();

ES6 为 JavaScript 带来了现代化的语法和强大的功能,极大地提升了开发效率和代码质量。在实际项目中,应该根据浏览器兼容性要求合理使用这些新特性,并考虑使用 Babel 等工具进行转译以支持旧版本浏览器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值