JavaScript Closure Not Working

Javascript closure not working

… var i …
async(function() { …
// errorLogging(tx, error, id);
(function(a, b, c) {
errorLogging(a, b, idsArray[c]);
})(tx, error, i);
… })

That's rather useless, because the i variable already does have the wrong values there. You need to put the wrapper around the whole async callback, closing over all variables are used within the async callback but are going to be modified by the synchronous loop.

The easiest way (works always) is to simply wrap the complete loop body, and close over the iteration variable:

for (var i = 0; i < paramsArray.length; i++) (function(i) { // here
var query = queryArray[i];
var params = paramsArray[i];
var id = idsArray[i];

window.logger.logIt("id: " + id);
tx.executeSql(query, params, function (tx, results) {
incrementSyncDownloadCount(results.rowsAffected);
}, function(tx, error) {
if (error.message.indexOf("are not unique") > 0 || error.message.indexOf("is not unique") > 0) {
incrementDuplicateRecordCount(1);
return false;
}
errorLogging(tx, error, id);
return true;
});
}(i)); // and here

You also might pass all variables that are constructed in the loop (and depend on the iteration variable) as the closure arguments. In your case, it might look like this:

for (var i = 0; i < paramsArray.length; i++) {
(function(query, params, id) { // here
window.logger.logIt("id: " + id);
tx.executeSql(query, params, function (tx, results) {
incrementSyncDownloadCount(results.rowsAffected);
}, function(tx, error) {
if (error.message.indexOf("are not unique") > 0 || error.message.indexOf("is not unique") > 0) {
incrementDuplicateRecordCount(1);
return false;
}
errorLogging(tx, error, id);
return true;
});
}(queryArray[i], paramsArray[i], idsArray[i])); // here
}

Or you identify the async callback, and wrap only that:

for (var i = 0; i < paramsArray.length; i++) {
window.logger.logIt("id: " + idsArray[i]);
tx.executeSql(queryArray[i], paramsArray[i], function (tx, results) {
incrementSyncDownloadCount(results.rowsAffected);
}, (function(id) { // here
return function(tx, error) {
// ^^^^^^ and here
if (error.message.indexOf("are not unique") > 0 || error.message.indexOf("is not unique") > 0) {
incrementDuplicateRecordCount(1);
return false;
}
errorLogging(tx, error, id);
return true;
};
}(idsArray[i]))); // and here
}

JavaScript closure inside loops – simple practical example

Well, the problem is that the variable i, within each of your anonymous functions, is bound to the same variable outside of the function.

ES6 solution: let

ECMAScript 6 (ES6) introduces new let and const keywords that are scoped differently than var-based variables. For example, in a loop with a let-based index, each iteration through the loop will have a new variable i with loop scope, so your code would work as you expect. There are many resources, but I'd recommend 2ality's block-scoping post as a great source of information.

for (let i = 0; i < 3; i++) {
funcs[i] = function() {
console.log("My value: " + i);
};
}

Beware, though, that IE9-IE11 and Edge prior to Edge 14 support let but get the above wrong (they don't create a new i each time, so all the functions above would log 3 like they would if we used var). Edge 14 finally gets it right.



ES5.1 solution: forEach

With the relatively widespread availability of the Array.prototype.forEach function (in 2015), it's worth noting that in those situations involving iteration primarily over an array of values, .forEach() provides a clean, natural way to get a distinct closure for every iteration. That is, assuming you've got some sort of array containing values (DOM references, objects, whatever), and the problem arises of setting up callbacks specific to each element, you can do this:

var someArray = [ /* whatever */ ];
// ...
someArray.forEach(function(arrayElement) {
// ... code code code for this one element
someAsynchronousFunction(arrayElement, function() {
arrayElement.doSomething();
});
});

The idea is that each invocation of the callback function used with the .forEach loop will be its own closure. The parameter passed in to that handler is the array element specific to that particular step of the iteration. If it's used in an asynchronous callback, it won't collide with any of the other callbacks established at other steps of the iteration.

If you happen to be working in jQuery, the $.each() function gives you a similar capability.



Classic solution: Closures

What you want to do is bind the variable within each function to a separate, unchanging value outside of the function:

var funcs = [];

function createfunc(i) {
return function() {
console.log("My value: " + i);
};
}

for (var i = 0; i < 3; i++) {
funcs[i] = createfunc(i);
}

for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}

problems with closure in JS

Line:1 invokes level1 fn and get back fn level2 stored in alias temp.

Line:2 invokes temp fn and get back fn level3 stored in alias temp2.

Line:3 now when invoking temp2 fn you execute fn level3 getting back the result of addition operation.

So temp3 is not a function but a value.

var a = 10;
function level1(b) { var c = 1;
function level2(f) { var d = 2;
function level3(g) { return a + b + c + d + f + g; } return level3; } return level2;}var temp = level1(10);var temp2 = temp(10);var temp3 = temp2(10);console.log(temp3); // or level(10)(); without variable

javascript closure, not working?

Well, the first function, returns a function, and you want the inner function to be executed.

If you invoke the result of it you will see it work, e.g.:

getZone()();

I think you want the following, use an immediately executed anonymous function, to call the $find method only once, storing its result:

var getZone = (function() {
var slidingZone = $find("<%= slidingZone.ClientID %>");
return function () { return slidingZone; };
})();

How do JavaScript closures work?

A closure is a pairing of:

  1. A function and
  2. A reference to that function's outer scope (lexical environment)

A lexical environment is part of every execution context (stack frame) and is a map between identifiers (i.e. local variable names) and values.

Every function in JavaScript maintains a reference to its outer lexical environment. This reference is used to configure the execution context created when a function is invoked. This reference enables code inside the function to "see" variables declared outside the function, regardless of when and where the function is called.

If a function was called by a function, which in turn was called by another function, then a chain of references to outer lexical environments is created. This chain is called the scope chain.

In the following code, inner forms a closure with the lexical environment of the execution context created when foo is invoked, closing over variable secret:

function foo() {
const secret = Math.trunc(Math.random() * 100)
return function inner() {
console.log(`The secret number is ${secret}.`)
}
}
const f = foo() // `secret` is not directly accessible from outside `foo`
f() // The only way to retrieve `secret`, is to invoke `f`

Javascript - Error ... is not a function inside a closure

Inside the onclick, this will be a reference to the DOM element that was clicked, not what this means where you're hooking it up.

If you want to access the object this refers to when you're setting up the handler, use a variable:

var thisObj = this;
for (...) {

...and then in the handler:

thisObj.displayImg(tags[x]);

Although in this case, since you don't need this to refer to the handler, you can make it a lot simpler with Function#bind:

for (var i = 0; i < tags.length; i++) {
var li = document.createElement('li');
ul.appendChild(li);
li.innerHTML = tags[i];
li.onclick = function(x) {
console.log(tags[x]);
this.displayImg(tags[x]);
}.bind(this, i);
}

Function#bind returns a new function that, when called, will call the original with a specific this value and any further arguments you give bind (followed by any arguments it receives at runtime).


Side note: You may as well just pass the tag in, rather than the index:

var thisObj = this;
for (var i = 0; i < tags.length; i++) {
var li = document.createElement('li');
ul.appendChild(li);
li.innerHTML = tags[i];
li.onclick = (function(tag) {
return function() {
console.log(tag);
thisObj.displayImg(tag);
};
})(tags[i]);
}

or

for (var i = 0; i < tags.length; i++) {
var li = document.createElement('li');
ul.appendChild(li);
li.innerHTML = tags[i];
li.onclick = function(tag) {
console.log(tag);
this.displayImg(tag);
}.bind(this, tags[i]);
}

Closure in node js not working as expected

var j = i; will set the value of i which is length of the array on first response and that is the reason you get 2 every time you log it.

Invoke a anonymous function as a second argument of http.get which will return inner function to handle response and it will also remember the environment in which it is created. Value of passed argument i will be there in the memory to be used later.

Try this:

var http = require("http");
var urls = ["http://yahoo.com", "http://google.com"];
for (var i = 0; i < urls.length; i++) { http.get(urls[i], (function(i) { return function(res) { res.setEncoding('utf-8'); res.on("data", function(d) { console.log(i); }); } })(i));}

Closure not working outside of the function scope

var later;

function outerFunc() {
var innerVar = "Inside Outer";
function innerFunc() {
console.log(innerVar);
}

later = innerFunc;
};

outerFunc(); //Don't run innerFunc, just set later = innerFunc
later(); // Execute innerFunc

So it logs it just one time.. It seems nice..



Related Topics



Leave a reply



Submit