0%

Frontend-Day16——Proxy

Proxy

监听对象的操作,有多个捕获器

set四个参数:

  • target:目标对象
  • property:将设置为key
  • value:新属性值
  • receiver:调用的代理对象

get函数有三个参数

  • target:目标对象
  • property:被获取的属性的key
  • receiver:调用的代理对象

监听对象

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
<script>
const obj = {
name: "why",
age: 18,
height:1.88
}

const objProxy = new Proxy(obj, {
set:function(target, key, newValue) {
console.log(`监听设置${key}的设置值`,newValue)
target[key] = newValue
},
get:function(target, key) {
console.log(`监听获得${key}`)
return target[key]
},
deleteProperty:function(target,key) {
console.log(`监听到删除${key}属性`)
},

has:function(target,key) {
console.log(`监听in判断${key}属性`)
return key in target
}


})

console.log(objProxy.age)
objProxy.name = "kk"
console.log(objProxy.name)
objProxy.address = "Pekin"
console.log(objProxy.address)

delete objProxy.name
console.log("age" in objProxy)
</script>

监听函数

apply, construct

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function foo(num1,num2) {
console.log(this, num1, num2)
}

const fooProxy = new Proxy(foo, {
apply: function(target, thisArg, otherArgs){
console.log("监听执行了apply")
target.apply(thisArg, otherArgs)
},

construct: function(target, otherArray){
console.log("监听了New 操作")
return new target(...otherArray)
}
})
fooProxy.apply("abc", [111,222])

Reflect

减轻Object类的方法来操作对象,以前经常使用Object.xxx方法来操作对象,现在直接用Relfect.xx来操作方法.

Reflect常常和Proxy搭配使用,reflect常见方法和Proxy中的方法对应也是13个.

receiver指的就是objProxy,特定场景receiver可以排上用场.

场景:此时在Obj中有有对象访问器,给obj设置属性时.本质上是通过对象访问器set来进行赋值,但此时set中的this指向的是obj,并不是objProxy,只有对objProxy操作时才监听得到,虽然此时可以监听得到objProxy.name = “kobe”这一步,但内部的真正赋值this._name = newValue是无法监听到的,因此receiver可以把对象访问器中的this的指向改掉,改成objProxy

三大好处:

  • ​ .避免直接操作对象
  • ​ 有布尔返回值,可以判断本次操作是否成功
  • ​ receiver就是外层Proxy对象,可以决定对象访问器中setter/getter的this的指向
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
<script>

const obj = {
_name: "why",
set name(newValue) {
console.log("this:", this)//默认是obj
this._name = newValue
},
get name() {
return this._name
}
}

const objProxy = new Proxy(obj, {
set: function(target, key, newValue, receiver) {
//1.避免直接操作对象
//2.有布尔返回值,可以判断本次操作是否成功
//好处3:receiver就是外层Proxy对象,可以决定对象访问器中setter/getter的this的指向
const isSuccess = Reflect.set(target, key, newValue, receiver)
if(!isSuccess) {
throw new Error(`set ${key} failure`)
}
console.log("Proxy设置被调用")
},
get: function(target, key, receiver){
console.log("Proxy获取被调用")
return Reflect.get(target, key,receiver)
}
})

objProxy.name = "kobe"
console.log(obj.name)
</script>

construct借用其他类的构造函数

1
2
3
4
5
6
7
8
9
10
11
function Person(name, age) {
this.name = name
this.age = age
}

function Student(name, age){
const _this = Reflect.construct(Person,["why", 18], Student)
//等同于Person.call(this, name, age)
}
const stu = new Student("whu", 18)
console.log(first)

Promise

解决异步函数调用的规范问题

三个状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script>
//括号里回调函数叫executor
const promise = new Promise((resolve, reject) => {
//状态一旦被确定就不会再更改,也不能再执行某一回调函数来改变状态
//1.待定状态pending
console.log(1112)
console.log(22233)
//2.兑现fulfilled
resolve("haha")
//or 拒绝状态rejected
reject("xixi")
})
promise.then(value=>{
console.log(value)
}).catch(err => {
console.log(err)
})
</script>

resolve传入值

  • 普通值或对象,那么这个值会作为then回调函数
  • 如果resolve传入的是另一个Promise,那么这个新Promise会决定原Promise的状态
  • 如果传入的一个对象中实现then方法,那么会执行该then方法,并根据then方法的结果来决定Promise的状态
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
const p = new Promise(() => {
setTimeout(() => {
resolve("p的resolve")
}, 2000)
})

//括号里回调函数叫executor
const promise = new Promise((resolve, reject) => {
//1.普通值
resolve([
{name:"macbook", price:998},
{name:"ipadpro", price:250},
])

//2.resolve(promise)
//如果resolve的值本身Promise对象,那么当前的Promise的状态会有传入的Promise来决定
resolve(p)

//3.resolve(thenable)
resolve({
then: function(resolve, reject) {
resolve("thenable value")
}
})
})
promise.then(value=>{
console.log(value)
}).catch(err => {
console.log(err)
})

then的返回值

  • 如果返回一个普通值,那么它处于fulfilled状态,并且会将结果作为resolve的参数

  • then方法是返回一个新的Promise,这个新Promise的决议是等到then方法传入的回调函数有返回值时,进行决议.

  • 返回一个thenable值,会调用then方法,决定状态

1
2
3
4
5
6
7
8
9
promise.then(res => {
console.log("第一个then",res)
return "xixi"
}).then(res => {
console.log("第二个then",res)
return "ccc"
}).then(res => {
console.log("第三个",res)
})

finally

无论是then还是reject,Finally必定会执行

1
2
3
4
5
6
7
8
9
10
11
const promise22 = new Promise((resolve, reject) => {
reject("bbb")
})

promise.then(res => {
console.log("then", res)
}).catch(err => {
console.log("catch", err)
}).finally(()=> {
console.log("abon")
})

类方法

resolve/reject

有时候已经有一个现成的内容希望将其转位Promise来使用,这个时候可以使用Promise.resolve方法来完成,因为不需要进行额外处理了,所以没必要再new一个对象来处理.(Promise.resolve的用法相当于new Promise并且执行resolve操作)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Promise.resolve("hello world").then(res => {
console.log("then结果",res)
})
//相当于
new Promise(resolve =>{
resolve("hello world")
})

Promise.reject("xixihaha").catch(err => {
console.log("rej结果",err)
})

真实开发场景:
const studentList = []
const promise = Promise.resolve(studentList)

promise.then(res => {
console.log("then结果",res)
})

all

  • 将多个Promise包裹在一起形成一个新的Promise
  • 新的Promise状态由包裹的所有Promise共同决定
    • 当所有Promise状态编程fulfilled状态时,新Promise状态为fulfilled,并且将所有Promise的返回值组成一个数组
    • 当有一个Promise状态为reject时,新的Promise状态为reject,并且将第一个rejct的返回值作为参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p1 resolve")
},3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p2 resolve")
},3000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p3 resolve")
},3000)
})
Promise.all([p1, p2, p3]).then(res => {
console.log("all promise res:",res)
})

allSettled

  • 会在所有Promise都有结果,无论是Fullfilled,还是Rejected时,才会有最终的状态

  • 并且这个Promise的结果一定是fulfilled

race

表示多个Promise相互竞争,谁想有结果,那么就使用谁的结果

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