以下代码是lodash中negate
函数的源代码。我们可以看到,当参数长度小于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);
};
}
答案 0 :(得分:0)
Sry,但我的水晶球还在修理中。因此,我只能对作者的意图给出最好的猜测。
我认为这里的重点不是switch
,而是让优化器将整个构造转换为这些路径中的一个,假设该函数将使用一组一致的参数进行调用。 / p>
基本上优化了整个构造,甚至将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参数? imo,这些是最常见的情况。而默认情况只是为了完整性而且(再次,我的意见)应该永远/很少被击中。
另一点可能是Function#call()
在我的经历中比Function#apply()
快一点。很少考虑它,但这是一个将被其他库使用的库,因此每个性能问题都可能会有所增加。