知识篇 -- JS ES6+新特性:现代JS

Ray Shine 2024/1/20 JavaScript进阶知识ES6ES2015

ECMAScript 2015 (ES6) 是JavaScript语言的一个里程碑式版本,引入了大量新特性,极大地提升了JavaScript的开发效率和代码质量。随后的ES版本(ES2016, ES2017, ...)也持续带来了许多有用的改进。掌握这些现代JavaScript特性,是成为一名优秀前端开发者的必备条件。

# 一、变量声明:letconst 块级作用域

ES6引入了 letconst,解决了 var 存在的许多问题,提供了更严格、更可控的变量声明方式。

  • let:声明块级作用域的变量,没有变量提升,不允许重复声明。
  • const:声明块级作用域的常量,没有变量提升,不允许重复声明,且声明时必须初始化,一旦赋值后不能再重新赋值(对于引用类型,其指向的内存地址不可变,但对象内部属性可变)。

示例

// var 的问题
var a = 1;
if (true) {
    var a = 2; // 覆盖了外部的 a
    console.log(a); // 2
}
console.log(a); // 2

// let 和 const 解决
let b = 1;
if (true) {
    let b = 2; // 块级作用域,与外部的 b 是不同变量
    console.log(b); // 2
}
console.log(b); // 1

const C = 10;
// C = 20; // TypeError
const obj = { name: "test" };
obj.name = "new test"; // 允许修改对象属性
// obj = {}; // TypeError

# 二、箭头函数 (Arrow Functions) 简洁语法

提供了一种更简洁的函数书写方式,并且解决了 this 的指向问题。

  • 语法简洁
    // 传统函数
    function add(a, b) {
        return a + b;
    }
    // 箭头函数
    const add = (a, b) => a + b;
    
    // 单个参数可省略括号
    const square = x => x * x;
    
    // 无参数需保留空括号
    const greet = () => "Hello!";
    
  • this 的词法作用域:箭头函数没有自己的 this 绑定,它会捕获其外层(词法)作用域的 this 值。这使得在回调函数中使用 this 变得更加直观。
    const person = {
        name: "Alice",
        sayHi: function() {
            setTimeout(function() {
                // console.log(`Hello, ${this.name}`); // 这里的this指向全局对象或undefined
            }, 1000);
        },
        sayHiArrow: function() {
            setTimeout(() => {
                console.log(`Hello, ${this.name}`); // 这里的this指向person对象
            }, 1000);
        }
    };
    person.sayHiArrow(); // 1秒后输出:Hello, Alice
    

# 三、模板字符串 (Template Literals) 字符串增强

使用反引号 ` 定义,允许嵌入表达式和多行文本,告别了繁琐的字符串拼接。

  • 字符串插值:使用 ${expression} 语法嵌入变量或表达式。
  • 多行字符串:直接在反引号中换行即可。
  • 示例
    const name = "Bob";
    const age = 25;
    const message = `My name is ${name} and I am ${age} years old.`;
    console.log(message); // My name is Bob and I am 25 years old.
    
    const html = `
        <div>
            <h1>Welcome</h1>
            <p>${message}</p>
        </div>
    `;
    console.log(html);
    

# 四、解构赋值 (Destructuring Assignment) 数据提取

允许从数组或对象中提取值,对变量进行赋值,语法简洁且可读性强。

  • 数组解构
    const numbers = [10, 20, 30];
    const [first, second, third] = numbers;
    console.log(first); // 10
    
    const [a, , c] = [1, 2, 3]; // 跳过第二个元素
    const [x, y, ...rest] = [1, 2, 3, 4, 5]; // 剩余元素
    
  • 对象解构
    const person = { name: "Charlie", age: 40 };
    const { name, age } = person;
    console.log(name); // Charlie
    
    const { name: userName, age: userAge } = person; // 重命名变量
    const { city = "New York" } = person; // 设置默认值
    

# 五、Promise:异步编程的解决方案 异步处理

Promise是处理异步操作的一种模式,解决了回调地狱(Callback Hell)问题,使异步代码更易于管理和阅读。

  • 状态pending (进行中), fulfilled (已成功), rejected (已失败)。
  • 方法then(), catch(), finally(), Promise.all(), Promise.race(), Promise.any(), Promise.allSettled()
  • 示例
    function fetchData() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                const success = true;
                if (success) {
                    resolve("Data fetched successfully!");
                } else {
                    reject("Failed to fetch data.");
                }
            }, 2000);
        });
    }
    
    fetchData()
        .then(data => console.log(data)) // Data fetched successfully!
        .catch(error => console.error(error))
        .finally(() => console.log("Fetch attempt finished."));
    

# 六、Async/Await:更优雅的异步编程 更简洁

asyncawait 是基于Promise的语法糖,使得异步代码看起来和写起来更像同步代码,进一步提高了可读性。

  • async 函数async 关键字用于声明一个异步函数。异步函数总是返回一个Promise。
  • await 表达式await 关键字只能在 async 函数内部使用,它会暂停 async 函数的执行,直到其等待的Promise解决(fulfilled)或拒绝(rejected)。
  • 示例
    async function loadData() {
        try {
            console.log("Start loading...");
            const data = await fetchData(); // 等待Promise解决
            console.log(data);
            console.log("Data processing complete.");
        } catch (error) {
            console.error("Error:", error);
        }
    }
    loadData();
    // 输出:
    // Start loading...
    // (2秒后) Data fetched successfully!
    // Data processing complete.
    

# 七、Class:面向对象编程的语法糖 OOP

ES6引入了 class 关键字,提供了更清晰、更简洁的方式来创建构造函数和实现继承,但其底层仍然是基于原型链的。

  • 定义类
    class Animal {
        constructor(name) {
            this.name = name;
        }
        speak() {
            console.log(`${this.name} makes a sound.`);
        }
    }
    
  • 继承:使用 extends 关键字实现继承,super() 调用父类构造函数。
    class Dog extends Animal {
        constructor(name, breed) {
            super(name);
            this.breed = breed;
        }
        speak() {
            console.log(`${this.name} barks.`);
        }
        static info() { // 静态方法
            console.log("Dogs are loyal.");
        }
    }
    
    const myDog = new Dog("Buddy", "Golden Retriever");
    myDog.speak(); // Buddy barks.
    Dog.info(); // Dogs are loyal.
    

# 八、模块化 (Modules):组织代码的新方式 代码组织

ES6引入了原生的模块系统,通过 importexport 关键字,使得JavaScript代码可以更好地组织和复用。

  • export:用于导出模块中的变量、函数、类。
    // math.js
    export const PI = 3.14159;
    export function add(a, b) {
        return a + b;
    }
    export default class Calculator { /* ... */ } // 默认导出
    
  • import:用于导入其他模块导出的内容。
    // main.js
    import { PI, add } from './math.js';
    import MyCalc from './math.js'; // 导入默认导出
    
    console.log(PI); // 3.14159
    console.log(add(1, 2)); // 3
    const calc = new MyCalc();
    
  • 特点:模块是独立的作用域,默认处于严格模式,可以按需加载。

# 九、Set 和 Map:新的数据结构 新数据结构

ES6引入了两种新的集合类型,提供了更高效的数据存储和操作方式。

  • Set:存储唯一值的集合,不允许重复。
    const mySet = new Set([1, 2, 2, 3, 4, 4]);
    console.log(mySet); // Set {1, 2, 3, 4}
    mySet.add(5);
    mySet.delete(1);
    mySet.has(2); // true
    
  • Map:存储键值对的集合,键可以是任意类型(包括对象),解决了传统对象只能用字符串作为键的限制。
    const myMap = new Map();
    myMap.set("name", "David");
    myMap.set(1, "number one");
    const objKey = { id: 1 };
    myMap.set(objKey, "object value");
    
    console.log(myMap.get("name")); // David
    console.log(myMap.has(objKey)); // true
    

# 十、Proxy 和 Reflect:元编程的利器 元编程

  • Proxy:用于创建一个对象的代理,从而实现对对象基本操作的拦截和自定义。
  • Reflect:一个内置对象,提供了一组静态方法,用于拦截JavaScript操作。

这些ES6+的新特性极大地提升了JavaScript的表达能力和开发体验,使得JavaScript能够更好地应对复杂的应用场景。

最后更新时间: 2025/11/20 22:59:30
ON THIS PAGE