Javascript Scoped For Loops Function

Here is an example of a situation where a simple JS loop does not behave as expected due to the fact that the loop variable is not in a separate area.

A often proposed solution is to create an unpleasant kind of loop code that looks like this:

for (var i in obj) { (function() { ... obj[i] ... // this new shadowed i here is now no longer getting changed by for loop })(i); } 

My question is, can this be improved? Can i use this:

 Object.prototype.each = function (f) { for (var i in this) { f(i,this[i]); } }; // leading to this somewhat more straightforward invocation obj.each( function(i,v) { ... v ... // alternatively, v is identical to ... obj[i] ... } ); 

when will I find out that I need a "copied loop"? It looks cleaner and should have similar performance with a normal loop (since it uses it in the same way).

Update. It seems that doing something with Object.prototype is huge, no, no, because it breaks almost everything.

Below is a less intrusive implementation:

 function each (obj,f) { for (var i in obj) { f(i,obj[i]); } } 

The call changes very little to

 each(obj, function(i,v) { ... v ... } ); 

So, I think I answered my question, if jQuery does it this way, it cannot go wrong. Any problems that I missed could give an answer.

+6
source share
2 answers

Your answer pretty much covers it, but I think the change in the original loop is worth noting, since it makes sense to use a regular loop when each() function is not suitable for any reason.

Update: Modified to use an example similar to the example referenced by the question in order to compare different approaches. The example had to be adjusted because the each() function requires the filled array to iterate over.

Assuming the following setup:

 var vals = ['a', 'b', 'c', 'd'], max = vals.length, closures = [], i; 

Using the example from the question, the initial cycle ends with the creation of 2n-functions (where n is the number of iterations), because during each iteration two functions are created:

 for (i = 0; i < max; i++) { closures[i] = (function(idx, val) { // 1st - factoryFn - captures the values as arguments return function() { // 2nd - alertFn - uses the arguments instead alert(idx + ' -> ' + val); // of the variables }; })(i, vals[i]); } 

This can be reduced to creating only n + 1 functions by creating a factory function once, before starting the loop and reusing it:

 var factoryFn = function(idx, val) { return function() { alert(idx + ' -> ' + val); }; }; for (i = 0; i < max; i++) { closures[i] = factoryFn(i, vals[i]); } 

This is almost equivalent to how each() can be used in this situation, which will also lead to a total of n + 1 functions. The factory function is created once and immediately passed as each() argument.

 each(vals, function(idx, val) { closures[idx] = function() { alert(idx + ' -> ' + val); }; }); 

FWIW, I think the advantage of using each() is that the code is a little shorter, and the creation of the factory function on the right, when it is passed to the each() function, clearly shows that this is its only use. The advantage of the for loop version, IMO, is the code that makes this loop right there, so the nature and behavior are completely transparent, and the each() function can be defined in another file written by someone else, etc.

+1
source

Global area

When something globally means that it is available from anywhere in your code. Take this for example:

var monkey = "Gorilla";

 function greetVisitor () { return alert("Hello dear blog reader!"); } 

If this code was run in a web browser, the function area would be a window, which would make it

available for everything that works in this web browser window.

Local area

Unlike a global scope, a local scope is when something is simply defined and available in

a certain part of the code, as a function. For instance,

function talkDirty () {

 var saying = "Oh, you little VB lover, you"; return alert(saying); } alert(saying); // Throws an error 

If you look at the code above, the variable message is only available in talkDirty

function. Outside of this, it is not defined at all. Please note: if you said you didn’t say

The var keyword is before it; it will automatically become a global variable.

It also means that if you have nested functions, the inner function will have access to

contains functions and function functions:

function saveName (firstName) {

function capitalizeName () {

 return firstName.toUpperCase(); 

} var capitalized = capitalizeName ();

 return capitalized; 

}

 alert(saveName("Robert")); // Returns "ROBERT" 

As you just saw, the internal capitalizeName function did not need any parameter that was sent, but had a complete

access to the firstName parameter in the external saveName function. For clarity, let's take another

Example:

function siblings () {

 var siblings = ["John", "Liza", "Peter"]; 

function siblingCount () {

 var siblingsLength = siblings.length; return siblingsLength; 

}

function joinSiblingNames () {

 return "I have " + siblingCount() + " siblings:\n\n" + siblings.join("\n"); 

}

 return joinSiblingNames(); 

}

 alert(siblings()); // Outputs "I have 3 siblings: John Liza Peter" 

As you just saw, both internal functions have access to an array of siblings in the containing function, and

each internal function has access to other internal functions at the same level (in this case

joinSiblingNames can access siblingCount). However, the siblingsLength variable in siblingCount is

available only in this function, i.e. in this area.

+1
source

All Articles