目录
- 一、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>