本节所要介绍的是关于 ES6 进阶部分的内容 ES6 干货指南 (中)
const sym= Symbol();
typeof
返回symbol
const sym= Symbol();
console.log(typeof sym); // symbol
const sym1 = Symbol("sym");
const sym2 = Symbol("sym");
console.log(sym1,sym2); // Symbol(sym) Symbol(sym)
console.log(sym1 === sym2); // false
const sym = Symbol("sym");
const obj = {
a : 1,
b : 2,
[sym] : 3 // 符号属性 [sym]
}
console.log(obj); // {a: 1, b: 2, Symbol(sym): 3}
const sym1 = Symbol("sym1");
const sym2 = Symbol("sym2");
const obj = {
a : 1,
b : 2,
[sym1] : 3,
[sym2] : 4,
}
for(const prop in obj)
console.log(prop); // a b
console.log(Object.keys(obj)); // (2) ["a", "b"]
console.log(Object.getOwnPropertyNames(obj)); // (2) ["a", "b"]
// 要枚举则需使用针对符号属性的方法 getOwnPropertySymbols(obj)
console.log(Object.getOwnPropertySymbols(obj)); // (2) [Symbol(sym1), Symbol(sym2)]
const sym = Symbol();
console.log(sym + 0); // Cannot convert a Symbol value to a number
迭代器基本结构,迭代返回结果为 遍历器对象 / 指针对象
const IterObj = {
next(){ // next() 用于得到下一个数据
return {
value : "xxx", // 数据值 迭代执行获取数据
done : "xxx" // 状态 判断是否有后续数据,一般为 boolean
}
}
}
/* 这里调用 IterObj.next() 输出的是指针对象 */
0
的位置)next()
指针自动下移,指针自动指向数据结构第一个成员,next()
返回值一个对象 {vlaue: 数据结构第一个数据, done: false}
......
next
下移,指针指向无数据位置(指向索引值为length
的位置),返回 {value: undefiend, done: true}
const arr = [1,2,3,4,5];
const iterator = {
i : 0,
next: function() {
var result = {
value : arr[this.i],
done : this.i >= arr.length
}
this.i ++;
return result;
}
}
console.log(iterator); // {i: 0, next: ƒ}
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: 4, done: false}
console.log(iterator.next()); // {value: 5, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
const arr = [1,2,3,4,5];
function createIterator(arr){
let i = 0;
return {
next(){
var result = {
value : arr[i],
done : i >= arr.length
}
i ++;
return result;
}
}
}
const iter = createIterator(arr);
console.log(iter.next()); // {value: 1, done: false}
console.log(iter.next()); // {value: 2, done: false}
console.log(iter.next()); // {value: 3, done: false}
console.log(iter.next()); // {value: 4, done: false}
console.log(iter.next()); // {value: 5, done: false}
console.log(iter.next()); // {value: undefined, done: true}
function createFeiboIterator(){
let prev1 = 1;
let prev2 = 1; //定义前两位
let n = 1; //当前第几位
return {
next(){
let value;
if(n <= 2){
value = 1;
}else{
value = prev1 + prev2; // C = A + B
}
const result = {
value,
done : false //迭代器数据量的多少,只关心是否拿得到下一个数据
}
prev2 = prev1; // B = A
prev1 = value; // A = C
n ++;
return result
}
}
}
const iterator = createFeiboIterator();
console.log(iterator .next()); // {value: 1, done: false}
console.log(iterator .next()); // {value: 1, done: false}
console.log(iterator .next()); // {value: 2, done: false}
console.log(iterator .next()); // {value: 3, done: false}
console.log(iterator .next()); // {value: 5, done: false}
Symbol.iterator
,则表示对象可以迭代for of
去遍历某一个数据结构的时候,首先找 symbol. iterator
找到了则遍历,未找都则输出 xxx is not iterrable
const arr = [1,22,3333,44444,55555];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // {value: 1, done: false}
// for of 遍历可迭代对象
for(const item of arr)
console.log(item); // 1 22 333 4444 55555
yield
可暂停,next()
可启动。每次暂停返回的是yield
后的表达式结果function
与函数名之间有 * )yield
表达式来定义不同的状态,关键字yield
只能在函数内部使用,表示产生一个迭代数据next()
方法函数内部逻辑开始执行,遇到yield
表达式暂停,返回指针对象 {value: " ", done: " "}
;next
方法,会从上次暂停的yield
处开始将生成器函数运行到下一个yield
关键字位置 ;直到最后返回的指针对象done: true
;yield
语句返回结果一般为undefined
,当调用next()
方法时传参内容会作为启动时yield
语句的返回值。return
方法,可以提前结束生成器函数,整个的迭代过程提前结束 function *test(){
console.log('第1次执行')
yield 1;
console.log('第2次执行')
yield 2;
console.log('第3次执行')
yield 3;
return "over";
}
const generator = test();
console.log(generator.next()); // 第1次执行 {value: 1, done: false}
console.log(generator.next()); // 第2次执行 {value: 2, done: false}
console.log(generator.next()); // 第3次执行 {value: 3, done: false}
console.log(generator.next()); // {value: "over", done: true}
console.log(generator.next()); // {value: undefined, done: true}
可以看出生成器原理上是封装了的迭代器,相比原生的迭代器他是更可操控的
next
方法时,可以传递参数,传递的参数会交给yield
表达式的返回值next
方法后停留的地方是"终点","起点"在上一个停留的地方,执行的内容也即是从起点到终点过程中的代码next
方法传参后的返回值,是起点yield
语句接收的。 function *test(){
let info = yield 1; // 第一次暂停
console.log(info);
info = yield 2; // 第二次暂停
console.log(info);
return "OVER";
}
const generator = test();
console.log(generator.next()); // {value: 1, done: false}
console.log(generator.next(222)); // 222 {value: 2, done: false}
console.log(generator.next(333)); // 333 {value: "OVER", done: true}
第一次执行 generator.next()
运行至第一次暂停,第一次启动无需传参,因为函数运行至第一次暂停才有yield
表达式语句,即启动时是从下标 0
开始,没有yield
表达式接收返回值 ;
第二次执行 generator.next()
运行至第二次暂停,第二次启动传参 222
,接收参数的yield
表达式是第一次暂停的yield
表达式,后续next
执行同理 ;
/* 在函数内部是调用别的生成器 一定要加上 * */
function *foo(){
yield "a";
yield "b";
}
function *bar(){
yield *foo();
yield 1;
yield 2;
return "OVER";
}
const generator = bar();
console.log(generator.next()); // {value: "a", done: false}
console.log(generator.next()); // {value: "b", done: false}
console.log(generator.next()); // {value: "1", done: false}
console.log(generator.next()); // {value: "2", done: false}
console.log(generator.next()); // {value: "OVER", done: true}
promise
对象promise
对象可以将异步操作以同步的流程表达出来,避免了层层嵌套的回调函数(回调地狱) // 创建 promise 对象(sync)
let promise = new Promise((resolve, reject) => {
// 初始化 promise状态为 pending
console.log("pending") ;
if(异步操作成功){
resolve("resolve"); // 成功:修改promise状态为 resolved
} else {
reject("reject"); // 失败:修改promise状态为 rejected
}
});
// 调用 promise 的 then(async)
promise.then(result=> {
console.log( result, "成功了!" );
},error => {
console.log( error, "失败了!" );
});
new Promise((resolve, reject) => {
console.log("未决阶段的处理函数是同步的,会立即执行!");
resolve("resolve");
});
then
函数是异步的,就算会立即执行,也是会加入等待队列中,加入微队列 new Promise(resolve => resolve("resolve")).then(result=> {
console.log("then 函数是异步的加入微队列 " );
});
then
可以只添加成功的回调函数,catch
可以单独添加失败的回调函数 let pro = new Promise((resolve, reject)=> {
if(Math.random() < 0.5){
resolve("resolve");
} else {
reject("reject");
}
})
/* then 只添加成功的回调函数 */
pro.then(result=> {
console.log(result); // resolve
});
/* catch 单独添加失败的回调函数 */
pro.catch(err => {
console.log(err); // reject Uncaught (in promise) reject
});
resolved
这是一个正常的已决状态,后续处理表示为result
回调函数rejected
这是一个非正常的已决状态,后续处理表示为error
回调函数如果当前的Promise
是未决的,得到的新的pro
对象是挂起状态
const pro = new Promise((resolve,reject) => {
// resolve();
});
console.log(pro); // Promise {}
通过调用then
以后,返回的是一个全新promise
对象
const pro = new Promise(resolve => resolve(1));
console.log(pro); // Promise {: 1}
const proThen = pro.then(result => result*2);
console.log(proThen); // Promise {}
这里有一个需要注意的点:理论上console.log(proThen)
执行顺序是早于pro.then()
的执行的。即这里的 pro.then()
状态正常输出应该是 Promise {
,[[PromiseStatus]]: "pending"
,[[PromiseValue]]: undefined
但实际上是:
那么这里的proThen
结果为何能正常打印出来?经过实验发现可以利用定时器延缓来pro.then()
的执行的,这样在pro.then()
还未执时可以在浏览器查看到pro.then()
正常的"pending"
状态,而如果等待定时器执行完毕再去查看pro.then()
则就是已经处理完成了的结果。因此,这里非正常输出状态,主要由浏览器处理所造成的。
返回的全新promise
对象调用then
方法,触发 resolved / rejected
?
细心的伙伴应该发现了上一个栗子返回的新的promise
对象,状态是
,因此新的promise
对象调用then
方法则执行成功的回调函数。那么新对象的
状态如何来的?
const pro = new Promise(resolve => resolve(1));
const proThen1 = pro.then(result => {
return result; // 控制台打印 proThen1 ==> Promise {: 1}
});
const proThen2 = pro.then(result => {
throw result; // 控制台打印 proThen2 ==> Promise {: 1}
});
const pro = new Promise((resolve,reject) => reject(1));
const proThen1 = pro.catch(error => {
return error; // 控制台打印 proThen1 ==> Promise {: 1}
});
const proThen2 = pro.catch(error => {
throw error; // 控制台打印 proThen2 ==> Promise {: 1}
});
上述栗子可以看到pro
对象状态无论是什么,调用then / catch
方法 :
将结果 return
,则新的promise
对象 PromiseStatus: "resolved"
,PromiseValue: 1
将结果 throw
,则新的promise
对象 PromiseStatus: "rejected"
,PromiseValue: 1
注意:这里返回的是非promise
对象
返回 pormise 对象
上一个栗子可以看到,新的promise
对象状态却决于前一个promsie
对象调用then/catch
的返回方式,但是这是建立在返回是非promise
对象状态。如果返回的是promise
对象呢?
1)return promise
,则新的promise
对象和返回的promise
状态及值保持一致
const promise1 = new Promise((resolve,reject) => resolve(1));
const promise2 = new Promise((resolve,reject) => reject(1));
const pro = new Promise(resolve => resolve());
const proThen = pro.then(result => {
return promise1 ; // 控制台打印 proThen1 ==> Promise {: 1}
});
const proThen = pro.then(result => {
return promise2 ; // 控制台打印 proThen2 ==> Promise {: 1}
});
2)throw promise
,则新的promise
对象状态为rejected
,PromiseValue
为返回的promise
对象
const promise1 = new Promise((resolve,reject) => resolve(1));
const promise2 = new Promise((resolve,reject) => reject(1));
const pro = new Promise(resolve => resolve());
const proThen1 = pro.then(result => {
throw promise1 ; // 控制台打印 proThen1 ==> Promise {: Promise}
});
const proThen2 = pro.then(result => {
throw promise2 ; // 控制台打印 proThen2 ==> Promise {: Promise}
});
Promise.resolve("resolve") 等价于 new Promise((resolve,reject) => resolve("resolve"));
Promise.reject("reject") 等价于 new Promise((resolve,reject) => reject("reject"));
promise
对象,如果里面所有的promise
对象都成功才会触发,一旦有一个失败,则该promise
对象为失败 const proms = [];
for(let i = 0; i < 10; i++){
proms.push(new Promise((resolve,reject) => {
Math.random() < 0.9 ? resolve(i) : reject(i);
}));
}
/**
* 所有的都成功才为成功,只要有一个失败,就失败
* proms数组存储的元素为不同状态的 promise 对象
* proms数组中,全是resolve状态,则pro状态:"resolved",pro值:Array(10),数组中元素为 promise值
* proms数组中,只要有reject状态,则pro状态:"rejected",pro值:数组中第一个reject状态下的 i 值
*/
const pro = Promise.all(proms);
pro.then(data => {
console.log('全部完成', data);
});
pro.catch(err => {
console.log('有失败的', err)
});
console.log(proms);
console.log(pro);
promise
对象的结果,不管这个结果成功还是失败 const proms = [];
for(let i = 0; i < 10; i++){
proms.push(new Promise((resolve,reject) => {
setTimeout(()=> {
console.log(i);
Math.random() < 0.6 ? resolve(i) : reject(i)
}, Math.random() * 3000 + 1000)
}))
}
/**
* 所有的都成功才为成功,只要有一个失败,就失败
* proms数组存储的元素为不同状态的 promise 对象
* race(proms)中的promise对象状态那个先执行,则pro状态和值与其保持一致
*/
const pro = Promise.race(proms);
pro.then(data => {
console.log('有人完成了', data);
})
pro.catch(err => {
console.log('有失败的', err);
})
console.log(pro);
/* 原生 promsie */
function promiseFoo(){
return new Promise(resolve => resolve("init promise"));
}
const initPro = promiseFoo();
console.log(initPro); // Promise {: "init promise"}
/* async */
async function asyncFoo(){
return "async promise";
}
const asyncPro = asyncFoo();
console.log(asyncPro); // Promise {: "async promise"}
next
方法,async 遇到 await
等待,当前的异步操作完成就往下执行then
方法链式操作await
取代 yield
async function asyncBar1(){
console.log(123);
return 456;
}
async function asyncBar2(){
console.log(789);
return 321;
}
async function asyncFoo(){
let result = await asyncBar1(); // 遇到 await 等待当前的异步操作完成再往下执行
console.log(result);
result = await asyncBar2();
console.log(result);
return 0;
}
console.log(asyncFoo());
console.log(asyncBar1());
console.log(asyncBar2());
关于 ES6 的进阶内容的干货先介绍这么多,后续有新的内容会再继续更新,Bye ~~~