I have created four different functions, like this:
var normal = function() {
return;
};
var control = function() {
return;
alert("Hello, world!");
};
var withArguments = function() {
return;
arguments;
};
var withEval = function() {
return;
eval("");
};
Since they all just do nothing and immediately return, I would expect all of them to have the same speed. But, after testing it on jsPerf, I find that normal and control execute about the same, but withArguments and withEval execute much more slowly.
Why would these unexecuted statements have any performance impact? Since they’re never executed, how is it possible for them to have any effect?
In short, calling
evalinside of a function and being able to access theargumentsarray both use extra set-up during function invocation. If it is known that neitherargumentsnorevalwill be executed, this extra set-up can be skipped.The compiler does not attempt to predict whether or not the
argumentsarray will actually be accessed or whetherevalwill actually be called, it only checks whether or not they exist in the function.argumentsIt is more expensive during runtime to invoke a variadic function that uses the
argumentsobject than a “normal” function that doesn’t use theargumentsobject.The extra steps required to bind the execution environment when the
argumentsobject is declared are specified in §10.6 of the ECMA-262 standard. Creating theargumentsobject is a somewhat expensive 15-step process. Basically,argumentshas to be populated with the passed-in arguments, and the.callerand.calleeproperties have to be created.The standard says that the
argumentsobject should be created when a function enters its execution context, unless there is already a parameter, variable, or function declared inside the function namedarguments.For purposes of optimization, most browsers do not actually create the arguments object unless the function actually uses it somewhere (even after a
return). This is why you see a performance hit whenargumentsis referenced, even when lines containing it are never executed.evalEntering
evalcode, as specified in §10.4.2 of the ECMA-262 standard, requires creating a special execution context. Basically, it has to bind all the properties of the calling function’s execution context to theevalcontext.If there are multiple
evals called in one function, they will basically both be doing the same process twice. For optimization, if browsers detect that there is anevalin the function (even after areturn), it pre-populates this new execution context that everyevalcan use, so that it doesn’t need to be recreated multiple times.Note that these optimizations are browser dependent and not required by the standard, so some browsers might not actually perform the optimizations described, or they might do things differently.