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) this._name = newValue }, get name() { return this._name } }
const objProxy = new Proxy(obj, { set: function(target, key, newValue, receiver) { 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) } 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> const promise = new Promise((resolve, reject) => { console.log(1112) console.log(22233) resolve("haha") 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) })
const promise = new Promise((resolve, reject) => { resolve([ {name:"macbook", price:998}, {name:"ipadpro", price:250}, ])
resolve(p)
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相互竞争,谁想有结果,那么就使用谁的结果