文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php教程>深入浅析ES6中的Proxy(代理)

深入浅析ES6中的Proxy(代理)

时间:2021-07-15  来源:互联网

今天PHP爱好者为您带来本篇文章带大家了解一下ES6中的Proxy(代理),通过几个代码实例来看看Proxy的使用方法。希望对大家有所帮助。

创建一个简单的Proxy

let target = {}
let proxy = new Proxy(target, {})

proxy.name = 'proxy'

console.log(proxy.name) // proxy
console.log(target.name) // proxy

target.name = 'target'

console.log(proxy.name) // target
console.log(target.name) // target

这个实例将"proxy"赋值给proxy.name属性时会在目标上创建name,代理只是简单的将操作转发给目标,他不会储存这个属性。相当于proxy.name和target.name引用的都是target.name的值。

使用set陷阱验证属性

set陷阱接收四个参数:

1.trapTarget:用于接收属性(代理的目标)的对象

2.key:要写入的属性键(字符串或者symbol)

3.value:被写入的属性值

4.receiver:操作发生的对象(通常是代理)

let target = {
   name: "target"
}

let proxy = new Proxy(target, {
   set(trapTarget, key, value, receiver) {
       if (!trapTarget.hasOwnProperty(key)) {
           if (isNaN(value)) {
               throw new TypeError("属性必须时数字")
           }
       }

       return Reflect.set(trapTarget, key, value, receiver)
   }
})

proxy.count = 1
console.log(proxy.count) //1
console.log(target.count) //1

proxy.name = "proxy"

console.log(proxy.name) //proxy
console.log(target.name) //proxy

proxy.other = "other" // 这里会报错因为不数字

这个实例每次在外面改变proxy的值时就会出发set函数。

用get陷阱验证对象结构

get接收3个参数

1.trapTarget:用于接收属性(代理的目标)的对象

2.key:要写入的属性键(字符串或者symbol)

3.receiver:操作发生的对象(通常是代理)

let proxy = new Proxy({}, {
   get(trapTarget, key, receiver) {
       if (!(key in receiver)) {
           throw new TypeError("属性" + key + "不存在")
       }

       return Reflect.get(trapTarget, key, receiver)
   }
})

proxy.name = "proxy"

console.log(proxy.name) //proxy

console.log(proxy.age) // 属性不存在会抛出错误

当我们访问proxy创建的对象属性时就会触发get方法

使用has陷阱因此已有属性

has接收2个参数:

1.trapTarget:用于接收属性(代理的目标)的对象

2.key:要写入的属性键(字符串或者symbol)

let target = {
   name: "target",
   value: 42
}

let proxy = new Proxy(target, {
   has(trapTarget, key) {
       if (key === 'value') {
           return false
       } else {
           return Reflect.has(trapTarget, key)
       }
   }
})

console.log("value" in proxy) // false
console.log("name" in proxy) // true
console.log("toString" in proxy) // true

用deleteProperty陷阱防止删除属性

deleteProperty接收2个参数:

1.trapTarget:用于接收属性(代理的目标)的对象

2.key:要写入的属性键(字符串或者symbol)

let target = {
   name: "target",
   value: 42
}

let proxy = new Proxy(traget, {
   deleteProperty(trapTarget, key) {
       if (key === "value") {
           return false
       } else {
           return Reflect.deleteProperty(trapTarget, key)
       }
   }
})

console.log("value" in proxy) // true

let result1 = delete proxy.value

console.log(result1) // false
console.log("value" in proxy) // true

console.log("name" in proxy) // true

let result2 = delete proxy.name
console.log(result2) // true
console.log("name" in proxy) // false

当外部要删除proxy的属性就会触发deleteProperty函数

原型代理陷阱(setProptotypeOf,getPrototypeOf)

setProptotypeOf接收2个参数

1.trapTarget:用于接收属性(代理的目标)的对象

2.proto:作为原型使用的对象

let target = {}

let proxy = new Proxy(target, {

   // 访问时调用
   getPrototypeOf(trapTarget) {
       return null
   },
   // 改变时调用
   setPrototypeOf(trapTarget, proto) {
       return false
   }

})

let targetProto = Object.getPrototypeOf(target)
let proxyProto = Object.getPrototypeOf(proxy)

console.log(targetProto === Object.prototype) //true
console.log(proxyProto === Object.prototype) // false
console.log(proxyProto) // null

Object.setPrototypeOf(target, {}) // 成功

Object.setPrototypeOf(proxy, {}) // 抛出错误

如果正常实现

let target = {}

let proxy = new Proxy(target, {

   // 访问时调用
   getPrototypeOf(trapTarget) {
       return Reflect.getPrototypeOf(trapTarget)
   },
   // 改变时调用
   setPrototypeOf(trapTarget, proto) {
       return Reflect.setPrototypeOf(trapTarget, proto)
   }

})

let targetProto = Object.getPrototypeOf(target)
let proxyProto = Object.getPrototypeOf(proxy)

console.log(targetProto === Object.prototype) //true
console.log(proxyProto === Object.prototype) // true

Object.setPrototypeOf(target, {}) // 成功

Object.setPrototypeOf(proxy, {}) // 成功

属性描述符陷阱

defineProperty接收三个参数:

1.trapTarget:用于接收属性(代理的目标)的对象

2.key:要写入的属性键(字符串或者symbol)

3.descriptor:属性的描述对象

let proxy = new Proxy({}, {
   defineProperty(trapTarget, key, descriptor) { // descriptor 只能接收enumerable, configurable, value, writeable, get, set
       if (typeof key === "symbol") {
           return false
       }
       return Reflect.defineProperty(trapTarget, key, descriptor)
   },
   getOwnPropertyDescriptor(trapTarget, key) {
       return Reflect.getOwnPropertyDescriptor(trapTarget, key)
   }
})

Object.defineProperty(proxy, "name", {
   value: "proxy"
})

console.log(proxy.name) //proxy

let nameSymbol = Symbol("name")

Object.defineProperty(proxy, nameSymbol, {
   value: "proxy"
})

在外部调用defineProperty | getOwnPropertyDescriptor时会触发内部definenProperty | getOwnPropertyDescriptor方法。

ownKeys陷阱

ownKeys陷阱会拦截外部的Object.keys(),Object.getOwnPropertyName(),Object.getOwnPropertySymbols()和Object.assign()四个方法

let proxy = new Proxy({}, {
   ownKeys(trapTarget) {
       return Reflect.ownKeys(trapTarget).filter(key => {
           return typeof key !== "string" || key[0] !== '_'
       })
   }
})

let nameSymbol = Symbol("name")

proxy.name = "proxy"

proxy._name = "private"

proxy[nameSymbol] = "symbol"

let names = Object.getOwnPropertyNames(proxy),
   keys = Object.keys(proxy),
   symbols = Object.getOwnPropertySymbols(proxy)

console.log(names.length) // 1
console.log(names) // name

console.log(keys.length) //1
console.log(keys[0]) // name

console.log(symbols.length) //1
console.log(symbols[0]) // symbol(name)

以上就是深入浅析ES6中的Proxy(代理)的详细内容,更多请关注php爱好者其它相关文章!

相关阅读更多 +
最近更新
排行榜 更多 +
元梦之星最新版手游

元梦之星最新版手游

棋牌卡牌 下载
我自为道安卓版

我自为道安卓版

角色扮演 下载
一剑斩仙

一剑斩仙

角色扮演 下载