使用JavaScript Object Proxy时如何获取this上下文 无需为每个实例创建代理
解法说明
原有实现无法获取实例上下文的核心原因是:直接挂载在原型上的Proxy和实例没有关联,访问实例.indexVar[i]时,Proxy的get钩子无法获取到上层的实例对象。
以下两种方案都不需要修改原有实例化逻辑,完全适配C++绑定生成高频实例的场景:
方案1:单例Proxy(零额外对象开销)
利用JS单线程执行的特性,通过临时变量存储当前访问的实例上下文,全程仅创建1个Proxy对象,性能最高。
注意:仅适用于不会单独保存
indexVar引用、每次都直接使用实例.indexVar[i]写法的场景。
let Actor = function () {} Actor.prototype = { getIndexVar: function (index) { return "actor :" + index }, name: function () { return "Actor" } } let Human = function () { this.getIndexVar = function (index) { return "Human :" + index } } Human.prototype = Actor.prototype // 核心实现 let currentInstance = null const indexVarProxy = new Proxy({}, { get(target, property) { return currentInstance.getIndexVar(property) } }) Object.defineProperty(Actor.prototype, 'indexVar', { get() { currentInstance = this return indexVarProxy } }) // 测试 let hum1 = new Human() console.log(hum1.indexVar[1]) // 输出:Human :1 let actor1 = new Actor() console.log(actor1.indexVar[2]) // 输出:actor :2
方案2:WeakMap缓存Proxy(兼容性最强)
通过WeakMap缓存每个实例对应的Proxy,每个实例仅会生成一次Proxy,WeakMap为弱引用,实例销毁时对应的Proxy会自动被GC回收,不会有内存泄漏问题,同时支持单独保存indexVar引用的场景。
let Actor = function () {} Actor.prototype = { getIndexVar: function (index) { return "actor :" + index }, name: function () { return "Actor" } } let Human = function () { this.getIndexVar = function (index) { return "Human :" + index } } Human.prototype = Actor.prototype // 核心实现 const proxyCache = new WeakMap() const indexVarHandler = { get(target, property) { return target.getIndexVar(property) } } Object.defineProperty(Actor.prototype, 'indexVar', { get() { if (!proxyCache.has(this)) { proxyCache.set(this, new Proxy(this, indexVarHandler)) } return proxyCache.get(this) } }) // 测试 let hum1 = new Human() const iv = hum1.indexVar console.log(iv[1]) // 输出:Human :1 let actor1 = new Actor() console.log(actor1.indexVar[2]) // 输出:actor :2 console.log(iv[3]) // 输出:Human :3,不受其他实例访问影响
内容的提问来源于stack exchange,提问作者L.kadin
相关产品推荐
相关产品推荐

