我的问题涉及通过函数内联进行现代浏览器优化。我认为我真的需要熟悉 V8、JavaScriptCore 和/或 SpiderMonkey 代码库的人来回答这个问题;或者至少是熟悉现代浏览器优化方法的人。
基本上我想知道是否有任何方法可以预测何时使用函数内联,以及如何利用它来优化性能并减少代码重复。
让我们以joi tempo 中的以下简单函数为例:
function limit(f, max) {
var count = 0, isFunction = typeof max == 'function';
if(!isFunction) max = max >>> 0 || 1;
return function limitedFunction() {
if(isFunction ? !max(count) : (count >= max)) return;
count++;
return f.apply(this, arguments);
};
}
此函数接受一个函数f
并返回一个包装函数,该函数限制可以通过包装调用原始函数的次数。例子:
var foo = limit(function() { console.log('foo'); }, 3);
foo(); // logs 'foo'
foo(); // logs 'foo'
foo(); // logs 'foo'
foo(); // doesn't log anything
foo(); // doesn't log anything
它还接受一个返回true
或false
作为其第二个参数(而不是数字)的函数:
var bar = limit(
function() { console.log('bar'); },
function() { return Math.random() > 0.5 ? true : false }
);
bar(); // randomly logs 'bar' or doesn't log anything
bar(); // randomly logs 'bar' or doesn't log anything
bar(); // randomly logs 'bar' or doesn't log anything
这是一个过于简单化、微不足道的例子,所以请耐心等待。我认为在不平凡的情况下有真正的应用程序,但我想使用一个简单的案例来了解浏览器如何进行或可以进行内联的根源。
重写此函数的一种方法(可能)(可能)会(非常轻微地)提高性能(我想)是将返回的结果function
分为两种情况,一种max
是函数,另max
一种是数字:
function limit(f, max) {
var count = 0, isFunction = typeof max == 'function';
if(!isFunction) max = max >>> 0 || 1;
return isFunction
? function limitedFunctionA() {
if(!max(count)) return;
count++;
return f.apply(this, arguments);
}
: function limitedFunctionB() {
if(count >= max) return;
count++;
return f.apply(this, arguments);
};
}
这样,每次都会isFunction
调用检查是否必须发生,但在确定是否返回 or 时仅调用true
一次。但是,这并不理想,因为存在一些冗余代码。false
limitedFunction
limitedFunctionA
limitedFunctionB
我的问题涉及以下重写:
function limit(f, max) {
var count = 0, isFunction = typeof max == 'function',
check = isFunction
? function() { return !max(count); }
: function() { return count >= max; };
if(!isFunction) max = max >>> 0 || 1;
return function limitedFunction() {
if(check()) return;
count++;
return f.apply(this, arguments);
};
}
所以这是我的问题......现代浏览器会足够聪明吗?
if(check()) return;
进入
if(!max(count)) return;
何时isFunction
为真,并且
if(count >= max) return;
什么时候isFunction
是假的?...防止调用额外check()
函数的需要,每次都不必要地将额外函数扔到堆栈上。