anonymous functions arguments not accessible to inner functions [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
I have been trying to do this
function test()
{
$.getJSON("http://myurl.com",function (data){
for( i=0; i<data.length; i++){
test = createElement('img');
test.onclick = function (){ myotherfun(data[i]); }
}
}
}
function myotherfun(data)
{
alert(data);
}
An error message states that data isn't covered by the scope.
Can some one explain why this happens?

Now that you've edited your question I can see the problem XD
The problem is that the onclick function will use the current values of data and (more importantly) i. So essentially it's looking for data[data.length], which by the definition of length doesn't exist.
Instead, you need to "lock" the value of the iterator. Here's how you can do it:
for(i=0; i<data.length; i++) {
(function(i) {
// do stuff that relies on i
})(i);
}

Related

How many times function executes inside for loop? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 2 years ago.
My question is simple if I have a for loop and I had a function inside it, how many times will the function execute.
eg:
for(i=0;i<3;i++){
console.log(i);
(function(i){
console.log(i)
})
}
If anyone has the answer can you please explain to me why?
Thanks in advance.
What about this case:
for (k=0; k<5;k++) {
$( '#a_' + k ).on('click', function() {
console.log("Clicking on a_" + k)
});
}
so when if I pass id as a_1, what will be the console print.
The anonymous function inside the for loop won't execute at all. It would have to be an immediately invoked function expression to get executed.
for(i=0;i<3;i++){
console.log(i);
(function(i){
console.log(i)
})(i); // pass (i) as argument to execute
}
What you had previously will never execute:
for(i=0;i<3;i++){
console.log(i);
(function(i){
// will never execute because this is function is never invoked
console.log(i)
})
}
In the first code snippet, the function runs 0 times. You have a function expression, but you never call it. To call it you need to add (<argument>) after the expression.
for(i=0;i<3;i++){
console.log(i);
(function(i){
console.log(i+10)
})(i)
}
In the second code snippet, all the buttons will log Clicking on a_5. Closures contain a reference to the variable, not a snapshot of its value when they were created. All the closures refer to the same k variable, and at the end of the loop it will be set to 5. So they all concatenate 5 to the log message.
See Javascript infamous Loop issue? and JavaScript closure inside loops – simple practical example for a detailed explanation and solutions.

JS, dynamic callback function (i.e. dynamic constants), click example [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
My code is:
for (i = 0; i < 3; i++) {
elem[i].click(function(event) { alert(i); });
}
Unfortunately that does not work. Any idea how to make it alert the same i as the i in elem[i].
Thank you!
You should use let for defining variable i. Unlike var, variables defined by let are block scoped. As a result, they won't be overwritten after each iteration.
for (let i = 0; i < 3; i++) {
elem[i].click(function(event) { alert(i); });
}
By the way, when ES6 is available, it's generally a bad idea to use closures in this case. It's kind of overkill.

Explaining IIFE Inside Loop [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
How do JavaScript closures work?
(86 answers)
Closed 6 years ago.
I read this article, but I have some issues understanding it.
var funcs = [];
for (var i = 0; i < 3; i++) {
(function IIFE(arg) {
funcs[arg] = function output() {
console.log("My value: " + arg);
};
})(i);
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
How can I explain the mechanism of this snippet?
Start: i has value of 0. IIFE gets the value of i and stores it in arg.
funcs[0] just get assigned to a function named output.
second time, when i is 1, funcs[1] gets a totally new function? Is this false?
.....
The problem is here, How does funcs[0](); know that arg was 0? How things interact?
Function output() looks up and ask IIFE function to give the required value? right? Can someone say which illustration is correct?
By Providing this picture, for example, number 1, I mean, when funcs[0]() gets executed, output looks for arg, it doesn't find it, then goes to higher scope and finds it. each function has it's own IIFE, for example. I'n not sure how far are this from Javascript or even programming world, but help me get it!

Instantiation when creating methods dynamically [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 9 years ago.
I have some JSON data, and I'm trying to create classes and methods dynamically based on that data:
var classes = JSON.parse(data);
var classesObj = {};
for(var c in classes){
var methods = classes[c].methods;
var methodsObj = {};
for(var m in methods){
methodsObj[m] = function(args){
return methods[m].property;
}
}
classesObj[c] = methodsObj;
}
return classesObj;
But my problem is if I call something like
firstClass.firstMethod()
The property that is returned is actually from lastClass.lastMethod() I'm pretty sure it's an instantiation problem, but I just can't seem to figure out where to go from here.
The problem is that the anonymous variables (c and m) are bound to the same variable outside of the your anonymous function. See Javascript closure inside loops - simple practical example.

Looping JS variable doesn't show the correct value inside the function [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Doesn't JavaScript support closures with local variables? [duplicate]
(7 answers)
Closed 8 years ago.
I need to do the following task. But this always alerts only "5" instead of 1,2,3,4 and 5. How can I fix this? Please help.
for(var x=1; x<=5; x++){
something.load(function(result){
alert(x);
});
}
This is due to closure. When the callback is runned, it will alert the variable in its current state (so after the loop).
To fix this, you can create a new closure which'll keep the variable state.
for(var x=1; x<=5; x++){
(function(x) {
something.load(function(result){
alert(x);
});
}(x));
}
For a more complete explanation of Closure, you can refer to this SO question: How do JavaScript closures work?
Or this article by a member of TC39 (EcmaScript standard body) http://www.2ality.com/2013/05/quirk-closures.html

Categories

Resources