提问人:Tibi Neagu 提问时间:3/20/2020 更新时间:3/20/2020 访问量:355
JavaScript - 行为类似于原始的代理对象
JavaScript - proxy object to behave like primitive
问:
我正在尝试构建一个系统,该系统在加载库之前“缓存”对库的调用。
这类似于 Google Analytics(分析)的“设置”代码对变量所做的操作 - 它被初始化为一个数组,该数组“缓存”对真实分析端点的调用,直到库加载完毕。当它这样做时,它会读取并重播呼叫。_gaq
ga.js
_gaq
我们之所以决定这样做,是因为我们的遗留代码包含对特定库的大量调用,这些库在 中同步加载。这大大增加了首次内容绘制的时间,因为评估和执行了大量的 JS。<head>
但是,代码中有太多的地方需要更改(包装在侦听器中),因此我们决定尝试使用解决方法。'DOMContentLoaded'
我们决定尝试使用 to catch 对库方法的调用,并在准备就绪后重播它们:Proxy
// Original code:
var ourLib = new OurLib({ ... });
// Throughout the site, calls such as:
var res1 = ourLib.doThis();
var res2 = ourLib.getThat(3);
下面是我们新代码正在执行的操作的“简化”版本:
// New code:
var ourLib = new Proxy({
calls: [],
}, {
get(target, prop) {
if (prop in target) {
return Reflect.get(...arguments);
}
const callref = { prop, args: [], placeholder };
target.calls.push(callref);
return function(...args) {
const placeholder = MakeResultPlaceholder(...);
callref.args = args;
callref.placeholder = placeholder;
return placeholder;
};
},
});
// Throughout the site, calls continue as before, except now they're 'stored' in `calls`
var res1 = ourLib.doThis();
var res2 = ourLib.getThat(3);
// Much later, the original lib is loaded, and
var ourRealLib = new OurLib({ ... });
__playbackCalls(ourLib.calls, ourRealLib);
// Replace the proxy with the real thing
ourLib = ourRealLib;
运行上述操作后,属性将如下所示:calls
[
{
prop: 'doThis',
args: [],
reference: ResultPlaceholder
},
{
prop: 'getThat',
args: [3],
reference: ResultPlaceholder
}
]
该函数遍历数组和每个方法,并存储在每个对象中。__playbackCalls
calls
apply
ourRealLib
args
calls.forEach(({ prop, args, reference }) => {
reference._value = ourRealLib[prop].apply(ourRealLib, args);
});
当需要使用代理调用的结果时,问题就来了。现在,正如你所看到的,调用返回一个对象(它本身就是另一个代理)。这些占位符保存在“播放”期间填充的属性。placeholder
_value
所以问题来了:
- 比方说,要返回一个 .
ourLib.getThat()
number
- 在第一次“运行”期间,由于整个代理的事情,会指向一个对象:
res1
placeholder
Proxy { _value: undefined }
- 真正的库被加载,“播放”完成,返回,所以会
ourRealLib.getThat(3)
23
res1
Proxy { _value: 23 }
- 我可以做任何事情来用作数字吗?像这样:
res1
console.log(res1 * 2); // 46
答: 暂无答案
评论
res1 = { getValue() { this._value; } };
getValue
valueOf
valueOf
_value