可迭代对象
将Infos编程一个可迭代对象
- 必须实现一个特定的函数:[Symbol.iterator]
- 这个函数需要返回一个迭代器(这个迭代器用于迭代当前的对象)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <script> const infos = { friends: ["kobe", "james", "curry"], [Symbol.iterator]: function() { let index = 0 const infosIterator = { next: () => { if (index < this.friends.length) { return { done:false, value:this.friends[index++] } } else { return { done:true} } } } return infosIterator } } const iterator = infos[Symbol.iterator]() console.log(iterator.next()) console.log(iterator.next())
for(const item of infos){ console.log(item) }
const students = ["xixi", "haha","kk"] console.log(students[Symbol.iterator]) const studentIterator = students[Symbol.iterator]() console.log(studentIterator.next())
</script>
|
原生可迭代对象
String,Array, MapmSet, arguments对象,NodeList集合
应用场景
Js中的语法:for…of,展开语法,yield,解构赋值
创建一些对象,new Map([Iterable]), new WeakMap([iterable]), new Set([iterable]), new WeakSet([iterable])
一些方法调用:Promise.all(iterable), Promise.race(iterable), Array.from(iterable)
自定义类的对象迭代
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <script> class Person { constructor(name, age, height, friends) { this.name = name this.age = age this.height = height this.friends = friends }
running() {} [Symbol.iterator]() { let index = 0 const iterator = { next: () => { if (index < this.friends.length) { return { done: false, value: this.friends[index++] } } else { return { done: true} } } } return iterator } } </script>
|
生成器
更加灵活的控制函数什么时候继续执行,暂停执行
生成器也是一个函数,但是和普通函数有一些区别:
- 生成器函数需要阿紫function后面加一个*
- 生成器函数可以通过yield来控制函数执行流程
- 返回值是一个Genrator
参数和返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <script> function* foo(name1) { console.log("1111",name1); console.log("222", name1); const name2 = yield "aaa" console.log("333",name2); console.log("444",name2); yield "bbb" console.log("5555") console.log("666") return undefined } const generator = foo("第一次接受参数") console.log(generator.next()) console.log(generator.next("第二次接受参数")) console.log(generator.next()) </script>
|
提前结束
return传值后这个生成器函数就会结束,之后调用next不会继续生产值
1
| console.log(generator.return("终止"))
|
生成器替换迭代器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <script> const names = ["abc", "cba", "nba"] const nums = [100, 22, 42,54,123]
function* createArrayIterator(arr) { for (let i =0; i<arr.length; i++){ yield arr[i] } } function* createArrayIterator(arr) { yield* arr } const namesIterator = createArrayIterator(names) console.log(namesIterator.next()) console.log(namesIterator.next()) console.log(namesIterator.next()) </script>
|
生成器在类中替换迭代器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Person { constructor(name, age, height, friends) { this.name = name this.age = age this.friends = friends }
*[Symbol.iterator]() { yield* this.friends } }
const p = new Person("why",15,2.8,["curry","kobe","James"]) for (const item of p) { console.log(item) }
const pIterator = p[Symbol.iterator]() console.log(pIterator.next()) console.log(pIterator.next()) console.log(pIterator.next())
|
异步处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| <script> function requestData(url) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(url) }, 2000) }) }
function getData(){ requestData("why").then(res1 => { console.log("第一次结果",res1) requestData(res1+"kobe").then(res2 => { console.log("第二次结果",res2) requestData(res2+"LA").then(res3 => { console.log("第一次结果",res3) })
}) }) }
function getData() { requestData("why").then(res1 => { console.log("第一次结果",res1) return requestData(res1 + "kobe") }).then(res2 => { console.log("第二次结果", res2) return requestData(res1 + "james") }).then(res3 => { console.log("第三次结果" ,res3) }) }
function* getData() {
const res1 = yield requestData("why") console.log("res1", res1)
const res2 = yield requestData(res1 + "kobe") console.log("res2", res2)
const res3 = yield requestData(res2 + "james") console.log("res3", res3) } const generator = getData()
generator.next().value.then(res1 => { generator.next(res1).value.then(res2 =>{ generator.next(res2).value.then(res3 => { generator.next(res3) }) }) })
async function getData() { const res1 = await requestData("why") console.log("res1", res1)
const res2 = await requestData(res1 + "kobe") console.log("res2", res2)
const res3 = await requestData(res2 + "james") console.log("res3", res3) }
const generato2 = getData()
|
async 的返回值
异步函数有返回值时
- case1: 异步函数可以有返回值,但是异步函数返回值相当于被包裹在Promise.resolve中
- case2:异步函数返回值是Promise,状态由Promise决定
- case3:如果返回值是一个对象并且实现了thenable,那么会由对象的then方法来决定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <script> async function foo2() {
return { then: function(resolve, reject) { setTimeout(() => { resolve("bbb") }, 2000) } } }
foo2().then(res => { console.log("res", res) }) </script>
|
async的异常
如果在async中抛出异常,那么程序并不会像普通函数一样报错,而是会作为Promise的reject来传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
async function foo3() { console.log("---1") console.log("---2") "abc".filter() console.log("---3") }
foo3().then(res => { console.log("res", res) }).catch(err => { console.log("err", err) })
|
await关键字使用
- 只能在异步函数中使用
- await后面会跟上一个表达式,这个表达式会返回一个Promise
- awit会等到Promise变成fulfilled状态,之后再继续执行异步函数
- await也可以直接跟上一个异步函数调用(因为异步函数本来就直接返回一个Promise)
如果await后面返回的是reject,那么就得捕获
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| function bar_resolve() { return new Promise(resolve => { setTimeout(() =>{ resolve(123) },3000) }) }
function bar_reject() { return new Promise( reject => { setTimeout(() =>{ reject("error message ") },3000) }) }
async function foo() { console.log("----") const res1 = await bar_resolve() console.log(res1) console.log("++++") const res2 = await bar_reject() console.log(res2) console.log("++++") } foo().catch(err =>{ console.log("err",err) })
|
await和async结合使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| function why() { return new Promise((resolve) => { setTimeout(()=>{ resolve(123) },2000) }) }
async function test() { console.log("test function"); return test }
async function bar() { console.log("bar fun"); return new Promise((resolve) => { setTimeout( () => { resolve("bar") }, 2000) }) }
async function demo() { console.log("demo fun"); return new Promise((resolve) => { setTimeout( () => { resolve("demo") }, 2000) }) }
async function foo() { const res1 = await why() console.log(res1); const res2 = await test() console.log(res2); const res3 = await bar() console.log(res3); } foo()
|
微任务和宏任务(中级面试会考察)
macrotask: settimeout, ajax,setInterval,DOM监听, UIO rendering
microtask:Promise的then中的回调函数,Mutation Observer API, queueMicrotask()
浏览器执行顺序:在执行微任务优先.
错误处理
抛出异常
Error对象包含三个属性
- message:创建Error对象时传入的message
- name:Error的名称,通常和类的名称一致
- stack:整个Error的错误信息,包括函数调用栈,当我们直接打印Error对象时,打印的就是stack
Error的子类
- RangeError:下标值越界时使用的错误类型
- SyntaxError:解析语法错误时使用的错误类型
- TypeError出现类型错误时,使用的错误类型
1 2 3 4 5 6 7 8 9
| <script> function foo() { "abc".filter() throw new Error("我是错误信息") } foo() console.log("+++++"); </script>
|
捕获异常
1 2 3 4 5 6 7 8
| try{ foo() console.log("+++++") }catch(error){ console.log(error); } finally{ }
|