Skip to content

1.6 ES6+ 新特性

ES6(ECMAScript 2015)是 JavaScript 的一次重大更新,引入了许多新特性,极大提升了开发效率。

一、let 和 const

let(块级作用域)

javascript
// let 声明的变量拥有块级作用域
{
    let a = 10;
    console.log(a); // 10
}
// console.log(a); // 报错:a is not defined

// 不允许重复声明
let b = 20;
// let b = 30; // 报错

// 不会变量提升
// console.log(c); // 报错,不能在声明前使用
let c = 30;

const(常量)

javascript
// const 声明常量,必须初始化
const PI = 3.14159;

// 不能重新赋值
// PI = 3.14; // 报错

// 对象属性可以修改
const user = { name: "张三" };
user.name = "李四"; // 可以
// user = {}; // 报错

// 适用场景
// 1. 不需要改变的值
const MAX_VALUE = 100;
// 2. 导入的模块
const React = require("react");

二、解构赋值

数组解构

javascript
const arr = [1, 2, 3, 4, 5];

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

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

// 剩余元素
const [x, ...rest] = arr;
console.log(rest); // [2, 3, 4, 5]

// 默认值
const [d, e = 20] = [10];
console.log(d, e); // 10, 20

对象解构

javascript
const obj = { name: "张三", age: 25, city: "北京" };

// 基本解构
const { name, age } = obj;
console.log(name, age); // 张三, 25

// 重命名
const { name: userName, age: userAge } = obj;
console.log(userName, userAge); // 张三, 25

// 默认值
const { name: n = "李四" } = {};
console.log(n); // 李四

// 解构剩余属性
const { name, ...rest } = obj;
console.log(rest); // { age: 25, city: "北京" }

函数参数解构

javascript
// 对象参数解构
function greet({ name = "张三", age = 18 } = {}) {
    console.log(`姓名:${name},年龄:${age}`);
}

greet({ name: "李四", age: 25 });
greet(); // 使用默认值

三、模板字符串

javascript
const name = "张三";
const age = 25;

// 多行字符串
const str = `姓名:${name}
年龄:${age}`;

console.log(str);

// 表达式
const message = `姓名:${name},年龄:${age},成年:${age >= 18}`;

// 调用函数
function capitalize(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
}

console.log(`姓名:${capitalize(name)}`);

// 嵌套模板字符串
const info = `信息:${`姓名:${name},年龄:${age}`}`;

// 标签模板(高级用法)
function tag(strings, ...values) {
    console.log(strings);
    console.log(values);
    return strings.reduce((result, str, i) => {
        return result + str + (values[i] || "");
    }, "");
}

console.log(tag`姓名${name}年龄${age}`);

四、箭头函数

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

// 带大括号(需要 return)
const multiply = (a, b) => {
    return a * b;
};

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

// 单参数(可省略括号)
const square = x => x * x;

// 回调函数(常用场景)
const arr = [1, 2, 3, 4, 5];
const doubled = arr.map(x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

// 注意:箭头函数没有自己的 this
const obj = {
    name: "张三",
    greet: function() {
        const self = this;
        setTimeout(() => {
            console.log(this.name); // 正确指向 obj
            console.log(self.name); // self 也指向 obj
        }, 1000);
    }
};
obj.greet();

// 不适合作为对象方法(this 会指向外层)
const person = {
    name: "李四",
    sayName: () => {
        console.log(this.name); // undefined(this 指向全局或外层作用域)
    }
};

五、展开运算符

对象展开

javascript
const obj1 = { name: "张三", age: 25 };
const obj2 = { city: "北京" };

// 合并对象(后面的覆盖前面的)
const merged = { ...obj1, ...obj2 };
console.log(merged); // { name: "张三", age: 25, city: "北京" }

// 添加属性
const newObj = { ...obj1, city: "上海" };
console.log(newObj); // { name: "张三", age: 25, city: "上海" }

// 修改属性
const updated = { ...obj1, age: 26 };
console.log(updated); // { name: "张三", age: 26 }

// 复制对象(浅拷贝)
const copy = { ...obj1 };

数组展开

javascript
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

// 合并数组
const merged = [...arr1, ...arr2];
console.log(merged); // [1, 2, 3, 4, 5, 6]

// 添加元素
const newArr = [...arr1, 4, 5];
console.log(newArr); // [1, 2, 3, 4, 5]

// 函数调用参数(替代 apply)
const numbers = [1, 2, 3];
console.log(Math.max(...numbers)); // 3

// 数组复制(浅拷贝)
const copy = [...arr1];

六、数组的常用方法

javascript
const arr = [1, 2, 3];

// Array.from(从类数组创建数组)
const fromString = Array.from("hello");
console.log(fromString); // ['h', 'e', 'l', 'l', 'o']

// Array.of(创建数组)
const ofArray = Array.of(1, 2, 3);
console.log(ofArray); // [1, 2, 3]

// find(查找元素)
const found = arr.find(x => x > 1);
console.log(found); // 2

// findIndex(查找索引)
const index = arr.findIndex(x => x > 1);
console.log(index); // 1

// includes(是否包含)
console.log(arr.includes(2)); // true
console.log(arr.includes(4)); // false

// fill(填充)
const filled = new Array(3).fill(0);
console.log(filled); // [0, 0, 0]

// flat(扁平化)
const nested = [1, [2, [3, [4]]]];
const flat = nested.flat(2);
console.log(flat); // [1, 2, 3, [4]]

// flatMap(映射并扁平化)
const mapped = arr.flatMap(x => [x, x * 2]);
console.log(mapped); // [1, 2, 2, 4, 3, 6]

七、对象的新方法

javascript
const obj = { name: "张三", age: 25, city: "北京" };

// Object.keys(获取所有键)
console.log(Object.keys(obj)); // ["name", "age", "city"]

// Object.values(获取所有值)
console.log(Object.values(obj)); // ["张三", 25, "北京"]

// Object.entries(获取键值对数组)
console.log(Object.entries(obj)); // [["name", "张三"], ["age", 25], ["city", "北京"]]

// Object.fromEntries(从键值对数组创建对象)
const entries = [["name", "张三"], ["age", 25]];
const fromEntries = Object.fromEntries(entries);
console.log(fromEntries); // { name: "张三", age: 25 }

// Object.is(比较)
console.log(Object.is(NaN, NaN)); // true
console.log(NaN === NaN); // false
console.log(Object.is(+0, -0)); // false
console.log(+0 === -0); // true

// Object.assign(合并对象)
const obj1 = { name: "张三" };
const obj2 = { age: 25 };
const merged = Object.assign({}, obj1, obj2);
console.log(merged); // { name: "张三", age: 25 }

八、Promise

javascript
// 基本用法
const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("成功");
    }, 1000);
});

promise.then(
    data => console.log(data),
    error => console.error(error)
);

// Promise.all(全部成功才成功)
Promise.all([
    Promise.resolve(1),
    Promise.resolve(2),
    Promise.resolve(3)
]).then(([a, b, c]) => {
    console.log(a, b, c); // 1, 2, 3
});

// Promise.race(第一个完成的结果)
Promise.race([
    new Promise(resolve => setTimeout(() => resolve("A"), 100)),
    new Promise(resolve => setTimeout(() => resolve("B"), 200))
]).then(value => console.log(value)); // "A"

九、async/await(ES2017)

javascript
// 基本用法
async function fetchData() {
    try {
        const response = await fetch("https://api.example.com/data");
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error(error);
    }
}

fetchData();

// 并行执行
async function parallel() {
    const [data1, data2] = await Promise.all([
        fetch("url1"),
        fetch("url2")
    ]);
    console.log(data1, data2);
}

十、Classes(类)

javascript
// 基本类
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    greet() {
        console.log(`姓名:${this.name},年龄:${this.age}`);
    }
}

const person = new Person("张三", 25);
person.greet();

// 继承
class Student extends Person {
    constructor(name, age, school) {
        super(name, age);
        this.school = school;
    }

    study() {
        console.log(`${this.name} 在 ${this.school} 学习`);
    }

    greet() {
        super.greet(); // 调用父类方法
        console.log(`学校:${this.school}`);
    }
}

const student = new Student("李四", 20, "清华大学");
student.greet();
student.study();

// 静态方法
class MathUtil {
    static add(a, b) {
        return a + b;
    }
}

console.log(MathUtil.add(1, 2)); // 3

// Getter 和 Setter
class Circle {
    constructor(radius) {
        this._radius = radius;
    }

    get radius() {
        return this._radius;
    }

    set radius(value) {
        this._radius = value;
    }

    get area() {
        return Math.PI * this._radius ** 2;
    }
}

const circle = new Circle(5);
console.log(circle.area); // 78.5398
circle.radius = 10;
console.log(circle.area); // 314.159

十一、Set 和 Map

Set

javascript
// 创建 Set
const set = new Set([1, 2, 3, 3, 4, 4]);

// 特点:无重复值
console.log(set); // Set {1, 2, 3, 4}

// 添加元素
set.add(5);
set.add(5); // 不会重复添加

// 检查存在
console.log(set.has(3)); // true

// 删除元素
set.delete(3);

// 获取大小
console.log(set.size); // 4

// 遍历
set.forEach(value => console.log(value));

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

Map

javascript
// 创建 Map
const map = new Map([
    ["name", "张三"],
    ["age", 25]
]);

// 特点:键可以是任意类型
const obj = { id: 1 };
map.set(obj, "对象键");
console.log(map.get(obj)); // "对象键"

// 添加/获取
map.set("city", "北京");
console.log(map.get("name")); // "张三"

// 检查存在
console.log(map.has("name")); // true

// 删除
map.delete("age");

// 获取大小
console.log(map.size); // 2

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

十二、其他新特性

Symbol

javascript
// 唯一值,用作对象键
const symbol = Symbol("description");
const obj = {
    [symbol]: "唯一值",
    name: "张三"
};

console.log(obj[symbol]); // "唯一值"
console.log(obj.name); // "张三"

// 遍历时 Symbol 属性不会出现
for (let key in obj) {
    console.log(key); // 只输出 "name"
}

// 获取 Symbol 键
console.log(Object.getOwnPropertySymbols(obj));

函数参数默认值

javascript
function greet(name = "张三", age = 18) {
    console.log(`姓名:${name},年龄:${age}`);
}

greet(); // "姓名:张三,年龄:18"
greet("李四"); // "姓名:李四,年龄:18"
greet("王五", 20); // "姓名:王五,年龄:20"

剩余参数

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

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

总结

ES6+ 新特性极大提升了 JavaScript 的开发效率和代码可读性,掌握这些特性是现代前端开发的基础。