es6
模板字符串
ES6 中的模板字符串(template string)是一种增强版的字符串,用反引号(`)标识。模板字符串使得字符串的拼接和处理更加方便、灵活和易读,尤其在涉及多行文本和动态内容插入的情况下,可以减少代码的复杂性和冗余度。
let job = "程序员",
salary = "100";
let say = `现在${job}, ${salary}`;
解构赋值
ES6 中的解构赋值是一种方便的数据提取和赋值方式,它允许从数组或对象中提取值,并将其赋给变量。
数组的解构赋值
let [a, b, c] = [1, 2, 3];
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
// 可以跳过某些位置
let [x, , z] = [4, 5, 6];
console.log(x); // 4
console.log(z); // 6
// 可以使用剩余操作符 `...` 收集剩余的元素
let [m, n, ...rest] = [7, 8, 9, 10, 11];
console.log(m); // 7
console.log(n); // 8
console.log(rest); // [9, 10, 11]
对象的解构赋值
let { name, age } = { name: "John", age: 30 };
console.log(name); // John
console.log(age); // 30
// 可以给变量起不同的名字
let { name: myName, age: myAge } = { name: "Jane", age: 25 };
console.log(myName); // Jane
console.log(myAge); // 25
// 可以设置默认值
let { city = "New York" } = {};
console.log(city); // New York
扩展运算符
ES6 的扩展运算符(...)是一种方便的操作符,它主要有以下功能:
展开数组或对象
console.log(...[1, 2, 3]); // 输出:1 2 3
console.log(1, ...[2, 3, 4], 5); // 输出:1 2 3 4 5
let obj1 = { foo: "bar", x: 42 };
let clonedObj = { ...obj1 };
console.log(clonedObj); // 输出:{ foo: "bar", x: 42 }
数组拷贝
let arr = [1, 2, [3, 4]];
let arr1 = [...arr];
arr1[2].push(5);
console.log(arr); // 输出:[1, 2, [3, 4, 5]]
console.log(arr1); // 输出:[1, 2, [3, 4, 5]]
合并数组或对象
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
var arr3 = [...arr1, ...arr2];
console.log(arr3); // 输出:[0, 1, 2, 3, 4, 5]
函数参数传递
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers)); // 输出:6
与解构赋值结合
const [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 输出:1
console.log(rest); // 输出:[2, 3, 4, 5]
字符串转字符数组
const title = "china";
const charts = [...title];
console.log(charts); // 输出:['c', 'h', 'i', 'n', 'a']
数组去重(结合 Set)
const arrayNumbers = [1, 5, 9, 3, 5, 7, 10, 4, 5, 2, 5];
const newNumbers = [...new Set(arrayNumbers)];
console.log(newNumbers); // 输出:[1, 5, 9, 3, 7, 10, 4, 2]
剩余参数
ES6 中的剩余参数语法允许将不定数量的参数表示为一个数组。
其语法形式为:在函数的最后一个命名参数前加上三个点(...),后面跟着参数名,例如:function(a, b,...theArgs){ // 函数体 } ,在这个例子中,theArgs 将收集该函数的第三个参数及以后的所有剩余参数。
function fun1(...theArgs) {
alert(theArgs.length);
}
fun1(); // 弹出"0", 因为 theArgs 没有元素
fun1(5); // 弹出"1", 因为 theArgs 只有一个元素
fun1(5, 6, 7); // 弹出"3", 因为 theArgs 有三个元素
function multiply(multiplier,...theArgs) {
return theArgs.map(function(element) {
return multiplier * element;
});
}
var arr = multiply(2, 1, 2, 3);
console.log(arr); // (2, 4, 6)
function sortRestArgs(...theArgs) {
var sortedArgs = theArgs.sort();
return sortedArgs;
}
alert(sortRestArgs(5, 3, 7, 1)); // 弹出 1, 3, 5, 7
// 剩余参数可以被解构
function f(...(a, b, c)) {
return a + b + c;
}
f(1) // NaN (b 和 c 是 undefined)
f(1, 2, 3) // 6
f(1, 2, 3, 4) // 6 (第四个参数没有被解构)
类
ES6 引入了类(class)的概念,使面向对象编程在 JavaScript 中更加清晰和直观。
模块化
ES6 引入了模块化的概念,这使得 JavaScript 代码的组织和管理更加清晰和高效。
一个模块就是一个独立的 JavaScript 文件。模块内的变量、函数、类等默认是私有的,只有通过 export 关键字导出的部分才能被其他模块使用。
导出
// 导出单个变量或函数
export const num = 42;
export function add(a, b) {
return a + b;
}
// 也可以将多个导出写在一处
const str = "Hello";
function subtract(a, b) {
return a - b;
}
export { str, subtract };
导入
import { num, add } from "./module1";
promise
1. Promise 由来
在以前我们实现异步是用的回调函数,当一个异步请求需要依赖上一个异步请求返回的结果的时候,就会形成如下这种的调用结构。
请求1(function (结果1) {
请求2(function (结果2) {
请求3(function(结果3)) {
请求4(function(结果4) {})
}
});
});
这种结构看着很杂乱且不易维护,被我们亲切的叫做 “回调地狱”。为了解决回调地狱的问题,Promise 就诞生了。
Promise 诞生的使命:优雅的去表示异步回调。
2. Promise 基础概念
2.1 创建 promise 实例
Promise 是一个构造函数,所以我们在调用一个 Promsie 的时候,要用 new Promsie 的方式去调用。
const ps = new Promise();
new Promise 接受一个函数类型的参数。这个函数又接收两个参数 resolve 和 reject,分别对映成功回调和失败回调。Promise 内部有 3 种状态 pending(进行时),fulfilled(已成功),rejected(已失败)。且这三种状态是不可逆的,只能由 pending 到 fulfilled,pending 到 rejected。resolve 使 promise 状态由 pending 到 fulfilled,reject 使 promise 状态由 pending 到 rejected。
const ps = new Promise(function () {});
const ps = new Promise(function (resolve, reject) {
let number = 10;
if (number >= 10) {
resolve(number);
} else {
reject("number 小于10");
}
});
2.2 实例方法
为了更好的控制下一步执行,又诞生了三个实例方法 then、catch、finally。
2.2.1 then 方法
then 方法一般接受两个参数 resolve、reject。分别对应成功时的回调和失败时的回调。
成功状态的 promise 实例
const ps1 = new Promise(function (resolve, reject) {
let number = 10;
if (number >= 10) {
resolve(number);
} else {
reject("number 小于10");
}
});
ps1.then(function (res) {
console.log(res);
});
失败状态的 promise 实例
const ps2 = new Promise(function (resolve, reject) {
let number = 9;
if (number >= 10) {
resolve(number);
} else {
reject("number 小于10");
}
});
ps2.then(
function (res) {},
function (err) {
console.log(err);
}
);
2.2.2 catch 方法
then 方法支持链式调用,then 的执行严重依赖上一步的结果,上一步如果没有结果,那么下一步就不会执行。但是每一步都写 reject 特别麻烦,所以诞生了 catch,then 就可以省略 reject 方法,reject 方法就交给 catch 执行,同时 catch 还可以捕获执行 resolve 的异常。
const ps2 = new Promise(function (resolve, reject) {
let number = 9;
if (number >= 10) {
resolve(number);
} else {
reject("number 小于10");
}
});
ps2
.then(function (res) {})
.catch(function (err) {
console.log(err);
});
2.2.3 finally 方法
有的时候,无论成功还是失败都需要执行一些操作,就诞生了 finally。我们可以在这做一些清理工作。
const ps2 = new Promise(function (resolve, reject) {
let number = 9;
if (number >= 10) {
resolve(number);
} else {
reject("number 小于10");
}
});
ps2
.then(function (res) {})
.catch(function (err) {
console.log(err);
})
.finally(function () {
console.log("end");
});
2.2.4 then 的链式调用
因为 then 方法支持链式调用,所以我们需要知道使用 then 方法会有什么效果。只要调用 promise 实例的 then 方法一定产生一个新的 promise,这个 promise 的状态由里面的函数决定。函数什么时候有结果,这个新 promise 状态什么时候由 pending 转 fulfilled。catch 和 finally 同理。
const ps = new Promise(function (resolve, reject) {
let number = 10;
if (number >= 10) {
resolve(number);
} else {
reject("number 小于10");
}
});
ps.then(function (res) {
return res * 10;
})
.then(function (res) {
return res + 2;
})
.then(function (res) {
if (res > 100) {
console.log(res);
} else {
console.log("最后结果小于100");
}
});
3. Promise 原型方法
为了满足更多的业务需要,又诞生了 6 个原型方法 Promise.all()、Promise.allSettled()、Promise.any()、Promise.race()、Promise.reject()、Promise.resolve()。且都会返回一个确定状态的 Promsie 对象。
统一使用两个成功异步 ps1、ps2。两个失败异步 ps3、ps4。作为测试用例。如下:
const ps1 = new Promise(function (resolve, reject) {
setTimeout(() => {
resolve("成功结果1");
}, 1000);
});
const ps2 = new Promise(function (resolve, reject) {
setTimeout(() => {
resolve("成功结果2");
}, 2000);
});
const ps3 = new Promise(function (resolve, reject) {
setTimeout(() => {
reject("失败结果1");
}, 3000);
});
const ps4 = new Promise(function (resolve, reject) {
setTimeout(() => {
reject("失败结果2");
}, 2000);
});
3.1 Promise.all()
通过数组的形式传入异步操作,所有的异步执行都成功,才执行成功,如果有一个失败了,就执行失败。例子如下:
都成功,执行 then 方法,成功返回结果,通过 res 以数组的方式返回
Promise.all([ps1, ps2])
.then(function (res) {
console.log("都成功", res);
})
.catch(function (err) {
console.log(err);
});
按传入顺序执行,如果有一个异步执行失败,中断其他异步操作,执行 catch 方法,通过 err 返回失败结果
Promise.all([ps1, ps2, ps3, ps4])
.then(function (res) {
console.log("都成功", res);
})
.catch(function (err) {
console.log("执行失败", err);
});
3.2 Promise.allSettled()
所有执行都有结果了就执行,无论成功还是失败
Promise.allSettled([ps1, ps2, ps3, ps4]).then(function (res) {
console.log("都返回结果", res);
});
3.3 Promise.any()
任意异步成功了就执行
Promise.any([ps1, ps2, ps3, ps4]).then(function (res) {
console.log("任意成功", res);
});
3.4 Promise.race()
任意异步成功或失败就执行。
Promise.race([ps1, ps2, ps3, ps4]).then(function (res) {
console.log("任意成功或失败", res);
});
3.5 Promise.reject()
返回一个状态为 rejected 的 Promise 对象
3.6 Promise.resolve()
会接收 4 种类型的参数:promise 实例 、具有 then 方法的对象、没有 then 方法的对象、不传参
当参数是一个 Promise 实例时,直接返回这个实例。
Promise.resolve(ps1);
当参数是一个具有 then 方法的对象时,将这个对象转为 Promise 对象,并立即执行对象的 then 方法
let obj = {
name: "yqcoder",
then(resolve) {
resolve(this.name);
},
};
Promise.resolve(obj);
当参数是一个没有 then 方法的对象,或者参数不是对象时,就会返回状态为 fulfilled 的新的 Promise 对象,并将参数传入下一个 then。
let obj = {
name: "yqcoder",
};
let ps = Promise.resolve(obj);
ps.then(function (res) {
console.log("结果", res);
});
当不带任何参数时,就会返回一个状态为 fulfilled 的 Promise 对象
Promise.resolve();
map/set
在 ES6 中,Map 和 Set 是两种新的数据结构,它们为数据的存储和操作提供了更强大和灵活的方式。
Map:Map 是键值对的集合,其中键可以是任何类型的值(包括对象),而不仅仅是字符串。
// 创建
let myMap = new Map();
myMap.set("key1", "value1");
myMap.set(2, "value2");
myMap.set({ name: "John" }, "value3");
// 获取
console.log(myMap.get("key1"));
console.log(myMap.get(2));
console.log(myMap.get({ name: "John" }));
// 检查键是否存在
console.log(myMap.has("key1"));
// 删除键值对
myMap.delete("key1");
// 获取 Map 的大小
console.log(myMap.size);
// 遍历 Map
for (let [key, value] of myMap) {
console.log(key + ': ' value);
}
Set:Set 是一种不允许重复值的数据结构。
// 创建
let mySet = new Set();
mySet.add(1);
mySet.add(2);
mySet.add(2); // 重复添加不会有效果
mySet.add("Hello");
// 检查元素是否存在
console.log(mySet.has(1));
// 删除元素
mySet.delete(1);
// 获取 Set 的大小
console.log(mySet.size);
// 遍历 Set
for (let item of mySet) {
console.log(item);
}
symbol
在 ES6 中,Symbol 是一种新的基本数据类型,它的主要目的是创建独一无二的值,通常用于对象的属性名,以避免属性名冲突。
let sym1 = Symbol();
let sym2 = Symbol("description"); // 可以提供一个可选的描述字符串
12. 迭代器和生成器
在 ES6 中,迭代器(Iterator)和生成器(Generator)为处理数据的遍历和生成提供了更强大和灵活的方式。
迭代器(Iterator)
迭代器是一个具有 next() 方法的对象,每次调用 next() 方法都会返回一个对象,该对象包含两个属性:value (当前迭代的值)和 done (一个布尔值,表示迭代是否完成)。
// 创建一个简单的迭代器
function createIterator(arr) {
let index = 0;
return {
next() {
if (index < arr.length) {
return { value: arr[index++], done: false };
} else {
return { value: undefined, done: true };
}
},
};
}
let iterator = createIterator([1, 2, 3]);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
生成器(Generator)
生成器是通过 function\* 定义的函数,可以通过 yield 表达式暂停和恢复执行,并且可以逐步生成一系列的值。
function* generateNumbers() {
yield 1;
yield 2;
yield 3;
}
let generator = generateNumbers();
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());

浙公网安备 33010602011771号