I have a function and I want to see what the value of index is. It gives me 0 however. I thought that was wierd so I put a console.log in function() to see if it was executing or not and I didn't recieve an output which tells me that function() isn't getting called. Not sure what I'm doing wrong.
function jsTest() {
var index = 0;
var counter = 0;
var obj = {};
obj.index = index; //obj.index = 0 at this point
var func = function () {
for (index = 0; index < 10; index++) {
counter += 2;
console.log(counter); //Doesn't execute for some reason
}
obj.index++;
};
obj.func = func; //executes function()
this.index++;
return index;
}
var x = jsTest();
console.log(x);
obj.func = func;
doesn't actually call func, it assigns the property func for obj to be the function func. If you want to call func, you should add parentheses afterwards, like
obj.func = func();
Related
var i = 5;
test();
function test() {
let i = 3;
alert(i);
}
The above example alerts the value of the second variable that is 3. How can I code it to alert the value of the first while keeping the two with the same name? Thanks
Use outside scope
var i = 5;
test();
function test() {
// let i = 3;
alert(i);
}
or make it a function parameter
// var i = 5;
test(5);
function test(i) {
// let i = 3;
alert(i);
}
Use it's global namespace, i.e. the global window variable.
var i = 5;
test();
function test() {
let i = 3;
alert(window.i);
}
What you probably want is this:
var i = 5;
test(i);
function test(x) {
alert(x);
}
I need to be able to build an array of anonymous functions that execute setTimeout with unique arguments per function. The following code has already been proposed, and works, on SO, but it only deals with immediate execution of the setTimeout. It does not explain how one can accumulate a collection of setTimeout functions to an array, with each setTimeout function having its own closure that defines a unique variable to be used in the execution of the setTimeout.
This is what exists already on SO:
var strings = [ "hello", "world" ];
for(var i=0;i<strings.length;i++) {
setTimeout(
(function(s) {
return function() {
alert(s);
}
})(strings[i]), 1000);
}
This is one of many permutations of what I have tried:
var strings = [ "hello", "world" ];
var func_array = [];
for (var i=0; i < strings.length; i++) {
func_array.push(function() {
setTimeout(
(function(s) {
return function() {
alert(s);
}
})(strings[i]), 1000);
});
}
When apply() is called on func_array, the strings[i] value is the same for each call, i.e. the final member of the strings array.
Another attempt: here we make the function that gets pushed onto func_array self-executing in order to scope the strings[i] variable correctly. However, apply() sees only 'undefined' since the function has already executed.
var strings = [ "hello", "world" ];
var func_array = [];
for (var i=0; i < strings.length; i++) {
func_array.push(function(s) {
setTimeout(
(function(s) {
return function() {
alert(s);
}
})(s), 1000);
}(strings[i]));
}
Ideas?
Use Function.prototype.bind(). It becomes much simpler than it actually is.
var strings = [ "hello", "world" ];
var func_array = [];
for (var i=0; i < strings.length; i++) {
var fn = function(string){
return setTimeout(function(){ alert(string) } ,1000);
};
func_array.push(fn.bind(this, strings[i]));
}
This does what you want.
var strings = ["hello", "world"];
var func_array = [];
for (var i = 0; i < strings.length; i++) {
(function (s) {
var func = function () {
alert("String is " + s);
}
var futureFunc = function () {
setTimeout(func, 1000);
}
func_array.push(futureFunc);
} (strings[i]));
}
func_array[0]()
func_array[1]()
I have this function:
x = function() {
for (i = 0; i < window.document.querySelectorAll('.btn[href*="/p"]').length; i++) {
return window.document.querySelectorAll('.abtk[href*="/url"]')[i].href;
}
};
I would like to have in x the results of the function and now the function in self when I test it in console in Chrome. How can I do it?
Make it Immediate invoke function, so the function gets executes immediately after defining. Below is the syntax for that
x = (function() {
for (i = 0; i < window.document.querySelectorAll('.btn[href*="/p"]').length; i++) {
return window.document.querySelectorAll('.abtk[href*="/url"]')[i].href;
}
})();
Observe () at the end of function declaration.
So my basic setup is this:
for (var i = 0; i < 3; i++) {
var indices = [-1, -1, -1];
while (index == -1) {
// Do Stuff
index[i] = newIndex;
}
var press = function() { alert(i); };
new control({press: press});
}
Now when I press the each of the new controls instead of getting alert(0), alert(1) and alert(2) I get alert(3), alert(3) and alert(3).
I can kind of understand whats going on. Now my question: how can i pass the different indexes to the function as I intended?
It is because closure variable i, the solution is to create a private closure for each loop.
for (var i = 0; i < 3; i++) {
var indices = [-1, -1, -1];
while (index == -1) {
// Do Stuff
index[i] = newIndex;
}
var press = (function(myvar){
return function() { alert(myvar); };
})(i);
new control({press: press});
}
Use closure:
var press = (function (x) {
return function () {
alert(x);
};
})(i);
This way the current i value is saved in a safe place, a private function.
Note that declaring variables (with var) inside loops are not standard, you should declare the press variable outside the loop.
Just when I thought I understood closures...
The following code snippet:
function f() {
var a = [];
var i;
for (i = 0; i < 3; i++) {
a[i] = function () {
var x = i;
return x;
}
}
return a;
}
var a = f();
console.log(a[0]());
console.log(a[1]());
console.log(a[2]());
prints out 3, 3, 3. I don't understand why. I'm copying the value of 'i' to the local variable x, so there should be three x's: x0=0, x1=1. x2=2. How are all of them reading the final value of i?
Your problem is caused by each a[i] being, in fact, a closure. They all share the same i, which is evaluated when each a[i] is called, not when the loop executes. You need to create each closure with a separate context. For instance:
function f() {
var a = [];
var i;
for (i = 0; i < 3; i++) {
a[i] = makeClosure(i);
}
return a;
}
function makeClosure(i) {
return function () {
var x = i;
return x;
}
}
Even though the value of i changes in your for loop, it's still the same i variable. You need to shadow i in that scope and effectively pass it by value:
for (var i = 0; i < 3; i++) {
(function(x) {
a[x] = function() {
return x;
}
})(i);
}