前言
先说结论,不要在proxy以及劫持的情况下大量使用同步的强耗时代码,以及不要proxy频繁读取属性的对象。
能用object.definepeoperty的情况下不要使用proxy。
我的测试量应该已经算很大了,延迟其实还是相对个人认为可以接受的。
但是推荐大家依然注意这个问题。以防以后出现卡顿。
因为,你永远不知道写网页的那个脑瘫写的是什么操作
简易测试过程
这里我进行了1000万次的循环,分别为无代理,有代理,代理无Reflect函数,代理无捕获函数,以及Object.defineProperty函数代理。
代码如下
var target = {
a: 0,
};
fornum = 10000000;
console.time("time_normal");
let result_normal = 0;
for (let index = 0; index < fornum; index++) {
result_normal += target.a;
target.a = index;
}
console.timeEnd("time_normal");
target.a = 0;
let handle = {
get: function (target, prop, receiver) {
return Reflect.get(target, prop);
},
set(target, prop, value) {
return Reflect.set(target, prop, value);
},
};
let targetproxy = new Proxy(target, handle);
result_normal = 0;
console.time("time_proxy");
for (let index = 0; index < fornum; index++) {
result_normal += targetproxy.a;
targetproxy.a = index;
}
console.timeEnd("time_proxy");
target.a = 0;
let handlenoreflect = {
get: function (target, prop, receiver) {
return target[prop];
},
set(target, prop, value) {
return target[prop]=value;
},
};
let targetnoreflect = new Proxy(target, handlenoreflect);
result_normal = 0;
console.time("time_noreflect");
for (let index = 0; index < fornum; index++) {
result_normal += targetnoreflect.a;
targetnoreflect.a = index;
}
console.timeEnd("time_noreflect");
target.a = 0;
let handlenotrap = {};
let targetproxynotrap = new Proxy(target, handlenotrap);
result_normal = 0;
console.time("time_proxy_notrap");
for (let index = 0; index < fornum; index++) {
result_normal += handlenotrap.a;
handlenotrap.a = index;
}
console.timeEnd("time_proxy_notrap");
let b = 0;
Object.defineProperty(target, "a", {
get: function () {
return b;
},
set: function (str) {
b = str;
},
});
result_normal = 0;
console.time("time_define");
for (let index = 0; index < fornum; index++) {
result_normal += target.a;
target.a = index;
}
console.timeEnd("time_define");
运行结果
观察运行结果可知一千万次正常为90毫秒,如果使用了Object.defineProperty,毫秒数与未代理相差无几。
中间的三个是经过proxy代理的对象。
如果我们不使用任何的捕获函数,也就是notrap,其执行速度与无代理的执行速度等同(这里将在最后被推翻)
如果使用了捕获函数。
使用Reflect的情况下,执行速度比normal慢了4100毫秒左右,而不使用reflec的情况下,可以降低1000毫秒的延时。
然后我们再尝试反复引用对象下的属性,以及进行计算,这里我给出代码。
for (let index = 0; index < fornum; index++) {
result_normal += targetproxy.a;
targetproxy.a = index;
targetproxy.b.c=targetproxy.a
targetproxy.b.d=targetproxy.b.c+1;
}
然后运行进行测试
这里可以看到极大的拉开了差距
原生以及object.defineproperty几乎没有改变。
而proxy即使是无handle的proxy对象,依然会极大的延迟。
这是因为代理引发的,我们对其属性进行读写每次都要经过proxy。
其速度受到了极大的影响。
所以proxy的影响速度与proxy创建的对象的属性的读取次数有极大的关联。
所以我们可以得出一个结论。
能不用proxy尽量不要使用proxy。
proxy可以使用,但是不建议用于频繁读取属性的对象上,如果没有高频读取属性的对象是可以使用的。
影响的性能较少。
补充理论
还有一个问题就是
如果你书写原生js代码,很有可能浏览器对其进行一定程度的优化的,而proxy代理后则很难进行代码计算优化,为了保持计算的正确性。
以上为个人的一点看法,请不要当做实际情况,如果有测试性能差距特别大的情况可以在评论下贴出代码。
大家一起学习分析
结语
撒花~