最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 浅谈ES6的Proxy

    正文概述 掘金(JAY971231)   2021-07-01   378

    创建一个简单的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
    

    每当我们判断proxy中是否含有属性时会出发has函数

    用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

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元