JavaScript-代理对象的行为类似于原语

JavaScript-代理对象的行为类似于原语,javascript,object,ecmascript-6,javascript-objects,metaprogramming,Javascript,Object,Ecmascript 6,Javascript Objects,Metaprogramming,我试图构建一个系统,在库加载之前“缓存”对库的调用 这类似于Google Analytics“setup”代码使用\u gaq变量所做的操作-它被初始化为一个数组,用于“缓存”对真实分析端点的调用,直到加载ga.js库。当它这样做时,它读取\u gaq并重播调用 我们之所以决定这样做,是因为我们的遗留代码包含大量对特定库的调用,该库在中同步加载。这大大增加了第一次有内容绘制的时间,因为很多JS都是经过评估和执行的 但是,代码中有太多需要更改的地方(包装在'DOMContentLoaded'侦听器

我试图构建一个系统,在库加载之前“缓存”对库的调用

这类似于Google Analytics“setup”代码使用
\u gaq
变量所做的操作-它被初始化为一个数组,用于“缓存”对真实分析端点的调用,直到加载
ga.js
库。当它这样做时,它读取
\u gaq
并重播调用

我们之所以决定这样做,是因为我们的遗留代码包含大量对特定库的调用,该库在
中同步加载。这大大增加了第一次有内容绘制的时间,因为很多JS都是经过评估和执行的

但是,代码中有太多需要更改的地方(包装在
'DOMContentLoaded'
侦听器中),因此我们决定尝试使用变通方法

我们决定尝试使用
Proxy
捕获对库方法的调用,并在准备好后重播它们:

//原始代码:
var ourLib=new ourLib({…});
//在整个站点中,呼叫,例如:
var res1=ourLib.doThis();
var res2=ourLib.getThat(3);
下面是我们新代码的一种“简化”版本:

//新代码:
var ourLib=新代理({
电话:[],
}, {
获得(目标、道具){
如果(目标中的道具){
返回Reflect.get(…参数);
}
常量callref={prop,args:[],占位符};
target.calls.push(callref);
返回函数(…args){
常量占位符=MakeResultPlaceholder(…);
callref.args=args;
callref.placeholder=占位符;
返回占位符;
};
},
});
//在整个站点中,呼叫仍像以前一样继续,但现在它们“存储”在“呼叫”中`
var res1=ourLib.doThis();
var res2=ourLib.getThat(3);
//很久以后,原始库被加载,并且
var ourRealLib=new OurLib({…});
__回放调用(ourLib.calls,ourRealLib);
//用真实的东西替换代理
ourLib=ourRealLib;
在上面的运行之后,
calls
属性将如下所示:

[
{
道具:“doThis”,
args:[],
参考:ResultPlaceholder
},
{
道具:“getThat”,
args:[3],
参考:ResultPlaceholder
}
]
\uu playbackCalls
函数通过
调用
数组进行迭代,并使用存储在每个对象中的
参数应用
来自
ourRealLib
的每个方法

调用.forEach({prop,args,reference})=>{
引用._value=ourRealLib[prop].apply(ourRealLib,args);
});
当需要使用代理调用的结果时,问题就出现了。现在,正如您所看到的,调用返回一个
占位符
对象(它本身就是另一个代理)。这些占位符包含在“播放”期间填充的
\u值
属性

所以问题是:

  • 假设
    ourLib.getThat()
    用于返回一个
    数字
  • 在第一次“运行”期间,由于整个代理问题,
    res1
    将指向一个
    占位符
    对象:
    proxy{u值:未定义}
  • 加载真实库,“回放”完成,
    ourRealLib.getThat(3)
    返回
    23
    ,因此
    res1
    将是
    代理{u值:23}
  • 我可以做任何事情以便我们可以使用
    res1
    作为一个数字吗?比如:
console.log(res1*2);//46

否。您不能。我也怀疑你真的想要那样。您的示例将使用
res1={getValue(){this.\u value;}尽管如此。@jonaswillms
getValue
valueOf
?valueOf,已经很晚了…@jonaswillms
valueOf
的建议似乎能帮我完成任务。即使
\u value
是一个实际对象,而不仅仅是原语,它也可以工作。你为什么说你怀疑我真的想要那个?这样使用它有什么坏处吗?缓存调用的方法只适用于谷歌分析,因为人们知道它们不会返回任何东西。