Reputation: 8781
Is there any performance hit for writing a function such that local var
statements are replaced with arguments? Example:
function howManyMatch(arr, pattern, /*ignored:*/ i, l, total) {
l = arr.length;
total = 0;
for (i = 0, i < l; i++) {
if (pattern.test(arr[i]))
total++;
return total;
}
Some advantages:
var
statements;var
s as possible...and disadvantages:
arguments
can be altered in unexpected ways. See belowStill it might be an easy way for a minifier to automatically squeeze out more bits.
Update: a big disadvantage not mentioned so far: If a function is called with N parameters, the first N items in arguments
will be binded to the first N identifiers in the argument list (see the last bullet in 10.1.8). Consider this:
function processStuff(/*ignored:*/i, j, k) {
// use i/j/k to loop
// do stuff with the arguments pseudo-array
}
In the above example, if you called processStuff(stuff1, stuff2)
, setting i
and j
would overwrite arguments[0]
and arguments[1]
respectively.
Upvotes: 6
Views: 368
Reputation: 164
Chistian Johansen in "Test-Driven Javascript Development"(2011) states : "In general, the arguments object should only be used when formal parameters cannot solve the problem at hand, because using it comes with a performance price. In fact, merely referencing the object will induce some overhead, indicating that browsers optimize functions that don't use it."
Upvotes: 0
Reputation: 30996
I think readability and maintainability outweight filesize and microoptimizations here. It is much easier to read code that has the var
keyword. Besides that, one var
statement per scope should be sufficient (that is where JavaScript hoists them, anyway). All local variables are available everywhere in the local scope (regardless of the order they have been declared). So all local variables should be declared at the same position (at the beginning of the local scope) for best readability. These four bytes for the var
statement are really not worth introducing possible bugs by allowing the user to set the initial values of your local variables by calling that function with additional parameters. It breaks encapsulation (you can get this right, but you'll end up with more bytes than you saved by omitting var
). Besides that, it is really confusing to anyone that is trying to read your code.
Upvotes: 1
Reputation: 827406
I wouldn't do it for many of the reasons you already know, personally I don't like the fact of mixing the semantic meaning of arguments vs. variables, although at the implementation level, when the function is executed, they are just properties of the current variable object, they have different meaning IMO.
Now, answering the question, I don't think there's any performance impact.
Let me talk a bit about the the Variable Instantiation process, it takes place for Function Code, just before the function is executed (commonly known as "hoisting"), at first, all the Formal Parameters described for the function are bound to the current Variable Object (the current scope), and they are initialized with the values passed in the function call or undefined
if not supplied.
After that, all the identifiers that belong to all var
statements within the function are declared in the current scope, and initialized with undefined
(note that the assignments are made after this, the function body isn't actually being executed yet).
The third step are FunctionDeclarations, all the identifiers of function declarations are bound to the local scope, if an identifier was previously declared, its value is replaced, for example:
(function (a) {
return typeof a; // "function", not "string"
function a () {}
})('foo'); // <-- passing a string
I would recommend instead simply to use a single var
statement, at the top of the function:
function howManyMatch(arr, pattern) {
var l = arr.length,
total = 0, i;
for (i = 0, i < l; i++) {
if pattern.test(arr[i]) && total++;
return total;
}
That doesn't just organize your code, it would help you to prevent unwanted results due the function-only scope of JavaScript and the "hoisting" nature of var
, some tools like JSLint encourage this also.
Upvotes: 4
Reputation: 105888
No, don't do this. It's confusing and unnecessary. And I find your list of "advantages" to be quite specious - every item on there is very thin as to the actual benefit gained.
If you must, just use the comma operator and declare all your variables in a single statement right at the head of the function (they're hoisted to this spot anyways.
function howManyMatch(arr, pattern) {
var i, l, total;
// rest
}
Or you can declare/define all in once step too
function howManyMatch(arr, pattern) {
var l = arr.length, total = 0, i = 0;
// rest
}
Upvotes: 5
Reputation: 22438
The same advantages you give, can be achieved by just removing the var
keyword:
function howManyMatch(arr, pattern) {
l = arr.length;
total = 0;
for (i = 0; i < l; i++) {
if pattern.test(arr[i]) && total++;
return total;
}
There's no need to explicitly write the var
keyword, as you are defining all variables in this case with a value ( l = arr.length
, total = 0
, i = 0
).
By the way, notice that you cannot predefine variables by defining them as function arguments. This is not possible, for instance:
function howManyMatch(arr, pattern, i=0, l, total = 0){ ... }
So, I don't think your solution to minify code is very useful after all, as the disadvantages remain ;)
Edit
I didn't think about the fact that defining variables without the var
keyword would turn them into globals. That might be something you don't want at all...
But as I think about the problem again, I don't see why you would want to define variables in function arguments. All advantages you give for that method, are basically true for this example too:
function howManyMatch(arr, pattern) {
var l = arr.length, total = 0, i=0;
for (; i < l; i++) {
if pattern.test(arr[i]) && total++;
return total;
}
And this example is even shorter.
Upvotes: 0