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:
- smaller minified size: no
var
statements; - less programmer time spent trying to use as few
var
s as possible - all local vars defined in one place
...and disadvantages:
arguments
can be altered in unexpected ways. See below- less clear in body that vars are local
- confusing to see arguments that don't do anything
- if someone unknowingly removes them, your code writes to globals
Still 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.
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:
- smaller minified size: no
var
statements; - less programmer time spent trying to use as few
var
s as possible - all local vars defined in one place
...and disadvantages:
arguments
can be altered in unexpected ways. See below- less clear in body that vars are local
- confusing to see arguments that don't do anything
- if someone unknowingly removes them, your code writes to globals
Still 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.
- My question was mostly about performance impact. I'll probably not use this practice.Several people don't seem to get that bining all var statements into one reduces readability: you're basically abusing the ma operator to cram multiple statements together. Seeing that Closure Compiler can do this optimization for you, it's more readable to just have one var declaration/assignment per line. – Steve Clay Commented Dec 8, 2010 at 23:17
5 Answers
Reset to default 5No, 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 ma 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
}
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 (monly 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 remend 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.
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.
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.
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 es with a performance price. In fact, merely referencing the object will induce some overhead, indicating that browsers optimize functions that don't use it."
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745184890a4615589.html
评论列表(0条)