以下代码是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);
};
}发布于 2017-12-07 19:16:17
但是我的水晶球还在修理中。所以我只能对作者的意图给出我最好的猜测。
我认为这里的重点不是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()快一点。很少有人去考虑它,但这是一个将被其他库使用的库,因此每个性能问题都可能会迅速增加。
https://stackoverflow.com/questions/47693024
复制相似问题