ES6新增的新特性以及用法

目录

  • 一、ES6介绍
    • [1.1 Let变量定义](#1.1 Let变量定义)
    • [1.2 箭头函数](#1.2 箭头函数)
      • [1.2.1 基本语法](#1.2.1 基本语法)
      • [1.2.2 this 绑定(重要区别!)](#1.2.2 this 绑定(重要区别!))
    • [1.3 模板字符串](#1.3 模板字符串)
    • [1.4 解构赋值](#1.4 解构赋值)
      • [1.4.1 数组解构](#1.4.1 数组解构)
      • [1.4.2 对象解构](#1.4.2 对象解构)
    • [1.5 扩展运算符](#1.5 扩展运算符)
      • [1.5.1 数组扩展](#1.5.1 数组扩展)
      • [1.5.2 对象扩展](#1.5.2 对象扩展)
    • [1.6 默认参数](#1.6 默认参数)
    • [1.7 剩余参数](#1.7 剩余参数)
    • [1.8 Symbol 类型](#1.8 Symbol 类型)
    • [1.10 Set 和 Map](#1.10 Set 和 Map)
      • [1.10.1 Set](#1.10.1 Set)
      • [1.10.2 Map](#1.10.2 Map)
    • [1.11 Promise 和异步](#1.11 Promise 和异步)
    • [1.12 async/await](#1.12 async/await)
    • [1.13 模块化](#1.13 模块化)
      • [1.13.1 导出](#1.13.1 导出)
      • [1.13.2 导入](#1.13.2 导入)

一、ES6介绍

ECMAScript 6(简称ES6)是于2015年6月正式发布的JavaScript语言的标准,正式名为ECMAScript 2015(ES2015)。它的目标是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言 。

另外,一些情况下ES6也泛指ES2015及之后的新增特性,虽然之后的版本应当称为ES7、ES8等。

1.1 Let变量定义

javascript 复制代码
function test1(){
            // var 声明的变量往往会越域
            // let 声明的变量有严格局部作用域
            {
                var a = 1;
                let b = 2;
            }
            console.log(a);  // 1
            //console.log(b);  // ReferenceError: b is not defined
        }

        function test1(){
            // var 可以声明多次
            // let 只能声明一次
            var m = 1
            var m = 2
            let n = 3
           //let n = 4
            console.log(m)  // 2
            console.log(n)  // Identifier 'n' has already been declared
        }

        function test2(){
            // var 会变量提升
            // let 不存在变量提升
            console.log(x);  // undefined
            var x = 10;
            console.log(y);   //ReferenceError: y is not defined
            let y = 20;

1.2 箭头函数

1.2.1 基本语法

javascript 复制代码
// 传统函数
function sum1(a, b) {
    return a + b;
}

// 箭头函数
const sum2 = (a, b) => a + b;

// 不同写法
const square = n => n * n;           // 单参数
const sayHello = () => 'Hello';      // 无参数
const log = msg => console.log(msg); // 单语句

// 多语句需要大括号
const calculate = (a, b) => {
    const sum = a + b;
    const product = a * b;
    return { sum, product };
};

// 返回对象需要用括号包裹
const createUser = (name, age) => ({ name, age });

1.2.2 this 绑定(重要区别!)

javascript 复制代码
// 传统函数的 this 问题
const obj1 = {
    name: '张三',
    sayName: function() {
        setTimeout(function() {
            console.log(this.name);  // undefined(this指向window)
        }, 100);
    }
};

// 箭头函数解决 this 问题
const obj2 = {
    name: '李四',
    sayName: function() {
        setTimeout(() => {
            console.log(this.name);  // '李四'(this继承自外层)
        }, 100);
    }
};

// 类方法中不要用箭头函数
class Person {
    constructor(name) {
        this.name = name;
    }
    
    // ❌ 错误:箭头函数在原型上,this不对
    sayName = () => {
        console.log(this.name);
    }
    
    // ✅ 正确
    sayName2() {
        console.log(this.name);
    }
}

1.3 模板字符串

javascript 复制代码
const name = '张三';
const age = 25;

// ES5
console.log('姓名:' + name + ',年龄:' + age);

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

// 多行字符串
const html = `
<div class="user-card">
    <h2>${name}</h2>
    <p>年龄:${age}</p>
    <p>状态:${age >= 18 ? '成年人' : '未成年人'}</p>
</div>`;

// 标签模板(高级用法)
function highlight(strings, ...values) {
    return strings.reduce((result, str, i) => {
        const value = values[i] ? `<span class="highlight">${values[i]}</span>` : '';
        return result + str + value;
    }, '');
}

const result = highlight`用户 ${name} 今年 ${age} 岁`;
// 输出:用户 <span class="highlight">张三</span> 今年 <span class="highlight">25</span> 岁

1.4 解构赋值

1.4.1 数组解构

javascript 复制代码
// 基本解构
const [a, b] = [1, 2];           // a=1, b=2
const [x, , z] = [1, 2, 3];      // x=1, z=3(跳过第二个)

// 默认值
const [n1 = 10, n2 = 20] = [1];  // n1=1, n2=20

// 剩余元素
const [first, ...rest] = [1, 2, 3, 4];  // first=1, rest=[2,3,4]

// 交换变量
let m = 1, n = 2;
[m, n] = [n, m];  // m=2, n=1

// 函数返回多个值
function getUser() {
    return ['张三', 25, '北京'];
}
const [userName, userAge, city] = getUser();

1.4.2 对象解构

javascript 复制代码
const user = {
    name: '张三',
    age: 25,
    address: {
        city: '北京',
        street: '朝阳路'
    }
};

// 基本解构
const { name, age } = user;           // name='张三', age=25

// 重命名
const { name: userName, age: userAge } = user;

// 默认值
const { name, gender = '男' } = user;  // gender='男'

// 嵌套解构
const { address: { city } } = user;    // city='北京'

// 函数参数解构
function printUser({ name, age = 18 }) {
    console.log(`${name} - ${age}岁`);
}
printUser({ name: '李四' });  // 李四 - 18岁

// 多次解构
function getData() {
    return {
        data: {
            users: [{ id: 1, name: '张三' }],
            total: 100
        },
        code: 200
    };
}
const { data: { users, total } } = getData();

1.5 扩展运算符

1.5.1 数组扩展

javascript 复制代码
// 复制数组
const arr1 = [1, 2, 3];
const arr2 = [...arr1];  // 深拷贝一层
arr2[0] = 100;          // arr1不受影响

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

// 函数参数
function sum(a, b, c) {
    return a + b + c;
}
const numbers = [1, 2, 3];
sum(...numbers);  // 6

// 替代 apply
Math.max(...[1, 2, 3]);  // 相当于 Math.max(1, 2, 3)

// 创建新数组
const newArr = [0, ...arr1, 4, 5];  // [0,1,2,3,4,5]

// 字符串转数组
const chars = [...'hello'];  // ['h','e','l','l','o']

1.5.2 对象扩展

javascript 复制代码
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };

// 合并对象(浅拷贝)
const merged = { ...obj1, ...obj2 };  // {a:1,b:2,c:3,d:4}

// 后面的覆盖前面的
const obj3 = { a: 1, b: 2 };
const obj4 = { b: 3, c: 4 };
const result = { ...obj3, ...obj4 };  // {a:1,b:3,c:4}

// 添加新属性
const user = { name: '张三', age: 25 };
const userWithId = { id: 1, ...user };  // {id:1,name:'张三',age:25}

// 默认值
const defaults = { theme: 'dark', fontSize: 14 };
const settings = { fontSize: 16, ...defaults };  // {theme:'dark',fontSize:14}

1.6 默认参数

javascript 复制代码
// ES5 方式
function greet(name) {
    name = name || '游客';
    return '你好,' + name;
}

// ES6 方式
function greet(name = '游客') {
    return `你好,${name}`;
}

// 表达式作为默认值
function createUser(name, role = 'user', createTime = new Date()) {
    return { name, role, createTime };
}

// 默认参数可以是函数调用
function getDefaultAge() {
    return 18;
}
function createPerson(name, age = getDefaultAge()) {
    return { name, age };
}

// 结合解构
function drawChart({ size = 'big', coords = { x: 0, y: 0 }, radius = 25 } = {}) {
    console.log(size, coords, radius);
}
drawChart();  // big {x:0,y:0} 25

// 注意事项:默认参数在函数参数列表中形成独立作用域
let x = 1;
function foo(x, y = () => { x = 2; }) {
    var x = 3;  // 这里不会影响参数x
    y();
    console.log(x);  // 3
}
foo();  // 输出 3

1.7 剩余参数

javascript 复制代码
// 收集剩余参数
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3, 4);  // 10

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

// 替代 arguments
function max(...args) {
    return Math.max(...args);
}

// 在箭头函数中(箭头函数没有arguments)
const max = (...args) => Math.max(...args);

// 解构中的剩余参数
const [first, second, ...others] = [1, 2, 3, 4, 5];
// first=1, second=2, others=[3,4,5]

const { a, b, ...rest } = { a: 1, b: 2, c: 3, d: 4 };
// a=1, b=2, rest={c:3,d:4}

1.8 Symbol 类型

javascript 复制代码
// 创建 Symbol
const sym1 = Symbol();
const sym2 = Symbol('description');  // 可选的描述
const sym3 = Symbol('description');

sym2 === sym3;  // false,每个 Symbol 都是唯一的

// 作为对象属性
const user = {
    name: '张三',
    [Symbol('id')]: 123,      // 不可枚举
    [Symbol.for('email')]: 'zhangsan@example.com'  // 全局 Symbol
};

// 获取 Symbol 属性
const symbols = Object.getOwnPropertySymbols(user);
console.log(symbols);  // [Symbol(id), Symbol(email)]

// 常用内置 Symbol
class MyArray {
    constructor(...args) {
        this.data = args;
    }
    
    // 自定义迭代行为
    [Symbol.iterator]() {
        let index = 0;
        const data = this.data;
        return {
            next() {
                return {
                    value: data[index++],
                    done: index > data.length
                };
            }
        };
    }
    
    // 转为原始值
    [Symbol.toPrimitive](hint) {
        if (hint === 'number') {
            return this.data.reduce((a, b) => a + b, 0);
        }
        if (hint === 'string') {
            return this.data.join(',');
        }
        return this.data.length;
    }
}

const arr = new MyArray(1, 2, 3);
[...arr];  // [1,2,3]
Number(arr);  // 6
String(arr);  // "1,2,3"

1.10 Set 和 Map

1.10.1 Set

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

// 基本操作
set.add(5);      // 添加元素
set.has(3);      // true
set.delete(2);   // 删除元素
set.size;        // 4
set.clear();     // 清空

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

// 集合操作
const set1 = new Set([1, 2, 3]);
const set2 = new Set([3, 4, 5]);

// 并集
const union = new Set([...set1, ...set2]);  // [1,2,3,4,5]

// 交集
const intersection = new Set([...set1].filter(x => set2.has(x)));  // [3]

// 差集
const difference = new Set([...set1].filter(x => !set2.has(x)));  // [1,2]

// WeakSet(弱引用)
const weakSet = new WeakSet();
const obj = {};
weakSet.add(obj);
console.log(weakSet.has(obj));  // true

1.10.2 Map

javascript 复制代码
// 创建 Map
const map = new Map();
map.set('name', '张三');
map.set('age', 25);

// 可迭代对象初始化
const map2 = new Map([
    ['name', '李四'],
    ['age', 30]
]);

// 基本操作
map.get('name');     // '张三'
map.has('age');      // true
map.delete('age');   // 删除
map.size;           // 1
map.clear();        // 清空

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

// 与 Object 对比
const objKey = {};
map.set(objKey, 'value');      // ✅ Map允许对象作为键
const obj = { [objKey]: 'value' };  // ❌ Object会把对象转为字符串"[object Object]"

// WeakMap(弱引用)
const weakMap = new WeakMap();
const element = document.getElementById('app');
weakMap.set(element, { clickCount: 0 });

1.11 Promise 和异步

javascript 复制代码
// 创建 Promise
const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        const success = Math.random() > 0.5;
        if (success) {
            resolve('操作成功');
        } else {
            reject(new Error('操作失败'));
        }
    }, 1000);
});

// 使用 Promise
promise
    .then(result => {
        console.log('成功:', result);
        return result.toUpperCase();
    })
    .then(upperResult => {
        console.log('处理后的结果:', upperResult);
    })
    .catch(error => {
        console.error('失败:', error.message);
    })
    .finally(() => {
        console.log('无论成功失败都会执行');
    });

// Promise 静态方法
Promise.all([
    fetch('/api/user'),
    fetch('/api/posts'),
    fetch('/api/comments')
])
.then(([user, posts, comments]) => {
    // 所有请求都成功
})
.catch(error => {
    // 任意一个失败
});

Promise.race([
    fetch('/api/data'),
    new Promise((_, reject) => 
        setTimeout(() => reject(new Error('超时')), 5000)
    )
]);

Promise.allSettled([
    Promise.resolve('成功'),
    Promise.reject('失败')
]).then(results => {
    console.log(results);
    // [
    //   { status: "fulfilled", value: "成功" },
    //   { status: "rejected", reason: "失败" }
    // ]
});

1.12 async/await

javascript 复制代码
// 基本用法
async function fetchData() {
    try {
        const response = await fetch('/api/data');
        if (!response.ok) {
            throw new Error('网络请求失败');
        }
        const data = await response.json();
        return data;
    } catch (error) {
        console.error('错误:', error);
        throw error;  // 重新抛出错误
    }
}

// 并行执行
async function fetchAllData() {
    // 并行执行
    const [user, posts] = await Promise.all([
        fetch('/api/user'),
        fetch('/api/posts')
    ]);
    
    // 顺序执行
    const userData = await user.json();
    const postsData = await posts.json();
    
    return { user: userData, posts: postsData };
}

// 在箭头函数中使用
const fetchUser = async (userId) => {
    const response = await fetch(`/api/users/${userId}`);
    return response.json();
};

// 在类方法中使用
class UserService {
    async getUser(id) {
        const response = await fetch(`/api/users/${id}`);
        return response.json();
    }
    
    // 注意:async 方法返回的是 Promise
    async updateUser(id, data) {
        const response = await fetch(`/api/users/${id}`, {
            method: 'PUT',
            body: JSON.stringify(data)
        });
        return response.json();
    }
}

// 立即执行 async 函数
(async () => {
    const data = await fetchData();
    console.log(data);
})();

// 错误处理最佳实践
async function process() {
    const result = await fetchData().catch(error => {
        console.error('处理错误:', error);
        return null;  // 返回默认值
    });
    
    if (result) {
        // 处理成功结果
    }
}

1.13 模块化

1.13.1 导出

javascript 复制代码
// math.js
// 命名导出
export const PI = 3.14159;
export function add(a, b) {
    return a + b;
}
export class Calculator {
    multiply(a, b) {
        return a * b;
    }
}

// 默认导出(一个文件只能有一个)
export default function() {
    console.log('默认导出');
}

// 聚合导出
export { add, PI } from './math.js';

1.13.2 导入

javascript 复制代码
// 导入命名导出
import { PI, add } from './math.js';

// 导入默认导出
import myFunction from './math.js';

// 重命名
import { add as addNumbers } from './math.js';

// 导入所有
import * as math from './math.js';
math.PI;  // 3.14159

// 动态导入
const module = await import('./math.js');
module.add(1, 2);

// 浏览器原生支持
<script type="module" src="app.js"></script>
相关推荐
LYFlied6 小时前
【一句话概述】前端性能优化从页面加载到展示
前端·性能优化
小番茄夫斯基6 小时前
Monorepo 架构:现代软件开发的代码管理革命
前端·javascript·架构
一只秋刀鱼6 小时前
从 0 到 1 构建 React + TypeScript 车辆租赁后台管理系统
前端·typescript
How_doyou_do6 小时前
pnpm优化理念 - 幻影依赖、monorepo - 升级npm
前端
雨落秋垣6 小时前
在前端把图片自动转换为 WebP 格式
前端
羽沢316 小时前
一些css属性学习
前端·css·学习
二狗哈7 小时前
Cesium快速入门22:fabric自定义着色器
运维·开发语言·前端·webgl·fabric·cesium·着色器
计算衎7 小时前
FastAPI后端和VUE前端的数据交互原理详解
前端·vue.js·fastapi
黑岚樱梦7 小时前
Linux系统编程
java·开发语言·前端