ES6
Generator
- 形式上:
function* genFun(...args){ // 规定了5个状态
yeild async1(); // 有yeild限制,不会立刻执行async1()
yeild async2();
yeild fun3();
yeild 4;
return 5 // 隐式声明为yeild
}
let gen=genFun("start");
- genFun返回一个可迭代对象。上述genFun虽然最终返回的是5,但打印genFun()得到的不是5,是一个可迭代对象。
- 这个可迭代对象,不是通过let…of来迭代,而是通过next来迭代。虽然,这个对象是类对象,但如果通过let…of这样来迭代,会产生以下问题:1.上面有5个状态,会忽略return声明的那个状态,也就是这剩下四个了;2.立马执行,不会暂停。
- 通过
.next(lastYeildResult)
,执行每个状态,并暂停。“执行下一个yeild并暂停”的意思。 - 简单过程
let gen=genFun("start")
创建一个Generator对象;"start"作为函数参数传入。let y1=gen.next(a1)
;指定下一个yeild并暂停,也就是执行async1()后暂停,返回async1()的结果。a1
是上一个yeild的结果,显然,因为我们是第一次运行next,所以上一个yeild为undefined,该参数没有意义。- 继续let y2=gen.next(a2);执行到下一个yeild,也就是async2(),那么这个时候a2就是上一个yeild(express)的结果了,上一个yeild(express)为yeild async1,显然,不论express为什么,这里指定了a2,那么,也就是yeild(express)=a2。
function* foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
return (x + y + z);
}
var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}
var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }
- 以此类推。
- 这种题,就想象有一个列表:
- let gen=[ yeild e1, yeild e2,…,yeild en];指针停留在下表为
-1
处 - gen.next(lastYeildResult)移动指针,执行下一个函数,并通过lastYeildResult告诉下一个函数,上一个yeild的结果是什么。
Promise对象
- new Promise(excutor);excutor是一个函数,会立刻执行;
- then里的回调函数,会进入微任务队列;then会返回一个新的promise对象
- await等到的是一定是一个已经resolved的Promise对象;
- 掌握几个常见的api:.all .allSetteled .race
- all 等待全部reslove,有一个为reject都会进入catch
- allSetteled只要全部fullfiled了就可以进入then回调了
- race取最先fullfiled的promise的结果
创建Promise
new Promise(excutor)
,excutor是一个函数,会立刻执行。可以接受两个入参resolve,reject。- Promise.resolve/reject()也会返回一个Promise对象
new Promise(()=>{})
new Promise((resolve)=>{})
new Promise((resolve,reject)=>{})
Promise.resolve();
Promise.reject();
- 只写一个
new Promise()
会报错:Promise resolver undefined si not a funciton
new Promise((resolve)=>console.log(1))
会立刻执行,输出1.
三个状态
pending
resolve
reject
// let p=new Promise() // 报错:Promise resolver undefined is not a function
let p1=new Promise(()=>{})
let p2=new Promise((resolve)=>{resolve("hi")})
let p3=new Promise((resolve,reject)=>{reject()})
console.log(p1,p2,p3)
// Promise {<pending>} Promise {<fulfilled>: 'hi'} Promise {<rejected>: undefined}
resolve/reject 和微任务的关系
new Promise((resolve,reject)=>{
console.log(1);
resolve(); // then中的回调会进入微任务队列;
console.log(2) // resolve()只会让then进入队列,不会打断2的输出
}).then(res=>{ // then返回一个新的Promise对象
console.log(3)
});
// 1 2 3
- 假设没有
resolve()
;then中的函数不会进入微任务队列,也就是不会输出。
await
难点在于,await fun,如果fun是一个Promise对象的情况;需要考虑一直取then的情况
async function a1(){
// return "hi"
// return new Promise(()=>{})
// return Promise.resolve();
}
async function a2(){
await a1();
console.log(1);
}
// main线程开始
a2();
Promise.resolve().then(()=>{
console.log(2)
})
- 首先思考一个问题,await是怎么实现等待的呢?
async function a2(){
await a1(); // a1不是Promise
console.log(1);
}
// 实际等同于
async function a2(){
a1().then(res=>{
console.log(1);
}}
}
- 看懂上面的例子,就很好的理解了,为什么a1会立刻执行,然后1会进入微任务;
- 假设res是一个Promise对象,也就是a1()是一个Promise对象会发生什么呢?
async function a2(){
await a1(); // a1是Promise对象
console.log(1);
}
// 实际等同于
async function a2(){
a1().then(res=>{
res.then(res2=>{
console.log(1)
)
}}
}
- 假设a1()返回的是Promise对象,也就是res是一个Promise,那么就会继续then。
- 注意,这里默认a1是用async标记的,假设a1没用async标记,即使a1返回的是promise对象,还是会被分解成这样,所以asynce标记a1的作用就是,不断得去取返回的值res,如果是promise,就接着嵌套,不断then,否则,只会then一次。
async function a2(){
a1().then(res=>{
console.log(1);
}}
}
反正,复制下面例子,判断对了,就算理解对了
async function a1(){ // 返回的是promise的时候,有无async会有什么区别?
// return "hi"
// return new Promise(()=>{})
// return Promise.resolve();
// return new Promise((resolve)=>{
// console.log(3)
// resolve()
// })
}
async function a2(){
await a1();
console.log(1);
}
a2();
Promise.resolve().then(()=>{
console.log(2)
})
打印p就好理解了,p是一个promise对象,状态为fulfilled;所以无论何时then,都能读到他的fulfilled值:‘hi’;
reject是一样的道理:
set vs weakSet
- 都是集合,只不过weakSet里面只能存引用类型的变量。
- weakSet相对set的好处就是,可以避免内存泄漏。weakSet里面存的引用,假设这个引用在外面被销毁了,那么weakSet里面的引用也会消失,就可以避免内存泄漏。
- 内存泄漏:某块内存,程序不再使用,但还是没有被释放。
map vs weakMap
- weak的表现和上面的一样,只不过之表现在key.key引用消失了,weakMap就删除键值对了.但是,value引用消失了,不影响.
- map和weakMap的区别是key;weakMap只允许对象,其实也就是弱引用做为键.