0%

Frontend-Day17——Iterator

可迭代对象

将Infos编程一个可迭代对象

  1. 必须实现一个特定的函数:[Symbol.iterator]
  2. 这个函数需要返回一个迭代器(这个迭代器用于迭代当前的对象)
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: () => {
// done: Boolean
// value:具体值/undefined
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 of操作
for(const item of infos){
console.log(item)
}

//可迭代对象必然包含一个[Symbol.iterator]函数
//数组是一个可迭代对象
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()) // {done: false, value:"aaa"}
console.log(generator.next("第二次接受参数")) // {done: false, value:"bbb"}
console.log(generator.next()) // {done: true, value:"undefined"}
</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)
})
}

//需求:
/*
1.发送一次网络请求,等到这次请求的结果
2.结合第一次结果,发送第二次网络请求
3.发送第三次
*/

// 方式一:
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)
})

})
})
}

//方式二 使用Promise进行重构
//链式调用
function getData() {
requestData("why").then(res1 => {
console.log("第一次结果",res1)
return requestData(res1 + "kobe")
//return结果会传给下一个then
}).then(res2 => {
console.log("第二次结果", res2)
return requestData(res1 + "james")
}).then(res3 => {
console.log("第三次结果" ,res3)
})
}

//方式三: 生成器
function* getData() {
//yield后的参数会作为返回对象的value

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() {

//1.返回一个普通值
// return ["abc", "cba","nba"]
// return 31

//2.返回一个promise
// return new Promise((resolve, reject) => {
// setTimeout(()=>{
// resolve("aaa")
// },3000)
// })

//3.返回一个thenable对象
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
//如果异步函数中抛出异常,这个异常不会立即被浏览器处理
//进行处理:Promise.reject(err)
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 {errorMessage:"错误信息"}
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{

}
-------------本文结束感谢您的阅读-------------