Javascript: assigning variables in functions

Consider these two blocks:

Block a

obj = { a: 1, b: 2, c: 3, f: function() { alert(this.a); alert(this.b); alert(this.c); } } 

Block B

 obj = { a: 1, b: 2, c: 3, f: function() { var a = this.a; var b = this.b; var c = this.c; alert(a); alert(b); alert(c); } } 

Is one of the methods more correct / efficient than the other? Of course, this is a concise example - there are more variables in my code, and I'm trying to save time by not typing this.varName every time in the functions, reassigning the variables for the current area of ​​the function. It works, but is it right?

EDIT:. To clarify, variables will be widely used in all functions. The general consensus seems to be that for this, reassignment through local reach is the way to go.

+8
javascript
source share
12 answers

It depends. If you intend to use the value once, it makes no sense to add storage overhead and then retrieve the value. If, on the other hand, you refer to a value several times in the scope of a function, it makes sense to retrieve it only once.

+7
source share

IN

 f: function() { a = this.a; b = this.b; c = this.c; alert(a); alert(b); alert(c); } 

not only global assignment and search are less efficient, but you pollute the global scope because a = this.a assigns global a .

EDIT:

Suppose this.a and this.b trigger a getter, and alert(a) calls the toString method of a .

There is an order of difference between

 var a = this.a, b = this.b; alert(a); alert(b); 

which does (get a, get b, toString, b toString) and

 alert(this.a); alert(this.b); 

which does (gets a, toString, gets b, b toString) and

Perhaps there is good reason to prefer one order of operations to another, but in terms of efficiency, the second is probably better.

Due to the difference in operations, you should not rely on a JavaScript minifier that preserves semantics to optimize the first or second when there is only one member use.

+4
source share

It all depends. If you only access the property once in your function, the first is faster. If you access it more than once, it’s faster to use a modified version of the second code snippet.

Changing the second version to declare a , b and c , since local vars f() will avoid multiple scans of the scope chain and bypass this - again if you need to access these properties several times.

+3
source share

Nicholas Zakas mentions this as a way to speed up your JavaScript. From the video summary:

Like global variables, performance can be improved by creating local variables to store object properties and array elements that are referenced several times. Also, keep in mind that a deeper property of an object and a search for an array element (for example, obj.name1.name2.name3) is slower.

+3
source share

The first way, if it is more efficient relative, because in the second case you make a copy of the variables, and therefore, one additional operator for all variables and a larger amount of memory will be occupied (both by code and variables).

+1
source share

You are missing a few key points in your examples. I will focus only on the function f , assuming the rest of the code is the same:

If you just refer to the values ​​stored on the object, there is no reason to store a temporary variable, it just inflates the work:

 function () { //use the values as they are alert( this.a ); alert( this.b ); alert( this.c ); } 

However, if you are performing calculations and you need to temporarily cache the results for reuse, you must use local variables. Make sure that they do not pollute the global area ( window object); use var to persist the variable locally.

 function () { var foo; foo = this.a / this.b + this.c; alert( this.a * foo ); alert( this.b / foo ); alert( this.c + foo ); } 

Edit to add:

There are two different types of variables. Variables attached to the object (accessed using this.varname or this['varname'] ) and variables that exist only in the local scope (which are declared using var varname and are accessible using varname ).

Any variable bound to an object is publicly available and should be used to identify data or persistence of function calls. Any variable declared inside a function is available only in the context of the function and therefore is private to the function. They do not store values ​​between calls, but they can be used to store data on calls to subfunctions.

Between Block A and Block B , Block A is the preferred method for interacting with object data, but in most cases, the function performs a large series of operations that are often associated with more complex behavior. If the function contained a callback that needed the values ​​of this.a , this.b and this.c , aliases should be used to transfer data, since this will change between contexts.

This will not warn 1 , 2 and 3 , as you would expect

 f:function () { $(foo).click(function g(){ //`this` does not refer to the object `f` belongs to, but the element being clicked on //and therefor is not likely to work as expected alert( this.a ); alert( this.b ); alert( this.c ); }); } 

This version will be:

 f:function() { var a,b,c; a = this.a; b = this.b; c = this.c; $(foo).click(function g(){ alert( a ); alert( b ); alert( c ); }); } 
+1
source share

If you can change the structure of the object a little, try putting the properties you need into the container (z) like this:

 obj = { z: { a: 1, b: 2, c: 3 }, f: function() { var z = this.z; for(var prop in z) { alert(z[prop]); } } } 
0
source share

1) The user must var to declare variables, otherwise they will be global.

2) Yes, copying the value can save you time while typing and will work faster, since accessing the properties of an object is not a really cheap operation. JavaScript does not implement arrays; they always hash.

0
source share
 var obj = { a: 1, b: 2, c: 3, f: function () { for (var property in this) { if (property != "f") alert(property + "=" + this[property]); } } }; obj.f(); 
0
source share

I expect you to want to place var in front of each of your variable declarations in block B. Otherwise, you are doing what you probably did not intend. Instead of assigning a value to a variable that is exclusive to the anonymous function that you assign to the f property, you should set the value for the a, b, c properties for the global object.

I expect that you want to place var before each variable a, b, and c in an anonymous function.

According to the book "High Performance Javascript" written by Nicholas Zakas, he mentions the cost associated with resolving an identifier (finding the name of the variable that you are using). He argues that local variables are the least expensive, while global variables are the most expensive.

So in your example (block B) given without var, what you are doing is expensive. If you have var, then what you are doing is optimal for identifier searches.

If you are interested in JS performance, I suggest you buy Nikolai’s book .

0
source share

If Donald Knuth, who said: “We must forget about little efficiency, say, about 97% of the time: premature optimization is the root of all evil,” were dead, he turned over in his grave. For me, I'm starting to feel this .

Please note boys and girls. Efficiency doesn't matter! This is just not!

Let her forget about the completely insane, like @Pheonix - it wrote "Phoenix" BTW! - actually worrying about the space occupied by local variables that return as soon as the function ends up screaming out loud and just focus on the original question. Consider the following bit of code:

 $(function() { var b; var d = { b : 1 } var n = 100000; var now = function() { return new Date().getTime(); }; var doTime = function(f) { var t = now(); f(); return now() - t; }; var tm1 = doTime(function() { for (var i=0; i<n; i++) { b = 1; } }); var tm2 = doTime(function() { for (var i=0; i<n; i++) { b = db; } }); $('body').empty().html("<table><tr><tr><td>Time without</td><td>" + tm1 + "ms</td><tr>" + "<tr><tr><td>Time with</td><td>"+ tm2 + "ms</td><tr>" + "<tr><tr><td>Total diff</td><td>"+ (tm2 - tm1) + "ms</td><tr>" + "<tr><tr><td>Avg. diff</td><td>"+ ((1000000.0 * (tm2 - tm1)) / n) + "ns</td><tr>" + "</table"); }); 

On my miserable five-year-old laptop, he says playing an object like this takes 90 nanoseconds. This means that you can do this eleven million times a second. Are you going to do it eleven million times? If not, do not waste one second worrying about it.

It is known that it is easier to optimize the correct code than to fix optimized code. Write your code well, then compare it. If it is too slow, identify bottlenecks (which I guarantee that you cannot hide the results of marking objects in local values) and eliminate them.

Now we will return you to your regular programming.

0
source share

As it is. Not. Since you do not use var to declare your variables, you declare these variables in the global scope, and not in the local scope.

If you are accessing the variable repeatedly, then it is definitely worth caching a copy in the local area. This is due to the fact that functions and objects have a chain of areas for searching if the variable is not available in the immediate area. In the following example, the innermost function must first search in its local region, then in the region of its parent function, and then finally in the outermost region of the function to find i . If i not present in this area, then he would also have to search for a global area.

 (function () { var i = 10; (function () { (function() { console.log(i); // i is 10 })(); })(); })(); 

The problem with caching variables in the local area is that sometimes the code can become difficult to read, and to a large extent any readability of the code increases the trump card's efficiency (a computer handles inefficient code much better than a person with poorly written code).


Declare your variables at the top of your function

If you are really concerned about efficiency / correctness, then declare all your variables at the beginning of the function. This allows javascript to be very effective at creating a local scope of a function. Declarations inside the function are inefficient, since javascript must first check if there is free space in the local area and, if necessary, change the size of the area. Be warned, even if you do not declare your variables at the top of the function, some compilers will do this for you, as this is part of the ECMA specification, which may lead to some errors). a source

eg.

 var i = 1; function test() { console.log(i); // undefined var i = 10; } test(); 

Essentially, the javascript engine compiled your code as:

 var i = 1; function test() { var i; console.log(i); // undefined i = 10; } test(); 

The version of your code has been fixed (if you needed to perform further operations using a, b or c).

 var obj = { a: 1, b: 2, c: 3, f: function() { var a, b, c; a = this.a; b = this.b; c = this.c; alert(a); alert(b); alert(c); } } 
0
source share

All Articles