下面的代码是源码negate
Lodash 中的函数。我们可以看到,当参数长度小于4时,它使用switch-case
而不是使用apply
直接地。这段代码有什么魔力呢?它会使性能更好吗?为什么分割点是4?
function negate(predicate) {
if (typeof predicate != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
return function() {
var args = arguments;
switch (args.length) {
case 0: return !predicate.call(this);
case 1: return !predicate.call(this, args[0]);
case 2: return !predicate.call(this, args[0], args[1]);
case 3: return !predicate.call(this, args[0], args[1], args[2]);
}
return !predicate.apply(this, args);
};
}
抱歉,我的水晶球还在修复中。所以我只能给你我对作者意图的最好猜测。
我认为这里的重点不是关于switch
而是让优化器能够将整个构造转换为这些路径中的单个路径,假设将使用一组一致的参数调用该函数。
基本上优化了整个结构,甚至内联了predicate
变成类似这样的伪代码。
假设函数总是用 2 个参数调用
function(){
//a gate to ensure the optimization is still correct/applicable
//probably more complex than this
if(arguments.length === 2){
//assign predicate function args
var value = arguments[0], index = arguments[1];
[function body of predicate]
}else{
[de-optimize]
//execute the de-optimized version of this function
}
}
为什么 0..3 个参数?在我看来,这些是最常见的情况。默认情况只是为了完整性,(再次,我的观点)不应该/很少被击中。
还有一点可能是,Function#call()
根据我的经验,比Function#apply()
。很少想到它,但这是一个将被其他库使用的库,因此每个性能问题都可能呈指数级增长。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)