Arguments to JavaScript Anonymous Function - javascript

for (var i = 0; i < somearray.length; i++)
{
myclass.foo({'arg1':somearray[i][0]}, function()
{
console.log(somearray[i][0]);
});
}
How do I pass somearray or one of its indexes into the anonymous function ?
somearray is already in the global scope, but I still get somearray[i] is undefined

The i in the anonymous function captures the variable i, not its value. By the end of the loop, i is equal to somearray.length, so when you invoke the function it tries to access an non-existing element array.
You can fix this by making a function-constructing function that captures the variable's value:
function makeFunc(j) { return function() { console.log(somearray[j][0]); } }
for (var i = 0; i < somearray.length; i++)
{
myclass.foo({'arg1':somearray[i][0]}, makeFunc(i));
}
makeFunc's argument could have been named i, but I called it j to show that it's a different variable than the one used in the loop.

How about a closure:
for (var i = 0; i < somearray.length; i++) {
var val = somearray[i][0];
myclass.foo({'arg1': val}, function(v) {
return function() {console.log(v) };
}(val) );
}

for (var i = 0; i < somearray.length; i++)
{
myclass.foo({'arg1':somearray[i][0]}, function(somearray)
{
console.log(somearray[i][0]);
});
}
And then in method foo call anonymous function with param.

You can pass variables values to annoymous function by using callback,
something like
myclass.foo(function(variable){
return function(){
console.log(variable);
}
})(variableValue);
);
check this post: https://shahpritesh.wordpress.com/2013/09/06/javascript-function-in-loop-passing-dynamic-variable-value/

All the functions/methods can be used as callbacks only. When you call the callback function you pass variables to it.
var myclass = {
foo: function(params, callback){
// do some stuff
callback(variable1, variable1, variableN);
}
}

Related

How to pass an object's method as a parameter to another function in Javascript

First take a look at my simple codes below:
function mySecondFunction(objArray,setFunc)
{
for (let i = 0; i < objArray.length; i++)
{
objArray[i].info.setTop(72);
}
}
function myFunction()
{
let myObjArray = [];
for (let i = 0; i < 10; i++)
{
myObjArray.push({
info:{topVar:0,
bottomVar:0,
get top() {return this.topVar;},
get bottom() {return this.bottomVar;},
setTop: function(input) {this.topVar = input;},
setBottom: function(input) {this.bottomVar = input; }
}
});
}
mySecondFunction(myObjArray); // This works Fine
mySecondFunction(myObjArray,setTop); // I want something like this!!!
}
As you can see, I want to pass a method of an object to another function. I know a lot of possible solutions to avoid this, but I want to know whether it is possible or not.
Detach it and pass as an argument. Remember to use call to set the intended this value.
function mySecondFunction(objArray, setFunc)
{
for (let i = 0; i < objArray.length; i++)
{
setFunc.call(objArray[i].info, 72);
/* explicitly telling that:
please set 'this' value in this function to be 'objArray[i].info' when running,
allowing, e.g. `this.topVar` in
`setTop: function(input) {this.topVar = input;}`
to be operating on `objArray[i].info.topVar` */
}
}
function myFunction()
{
let myObjArray = [];
for (let i = 0; i < 10; i++)
{
myObjArray.push({
info:{topVar:0,
bottomVar:0,
get top() {return this.topVar;},
get bottom() {return this.bottomVar;},
setTop: function(input) {this.topVar = input;},
setBottom: function(input) {this.bottomVar = input; }
}
});
}
mySecondFunction(myObjArray, myObjArray[0].info.setTop);
/* once detaching the method from the object,
(if we are not using arrow functions),
we lose 'this' value, meaning we are losing
the target of object that we want to operate on */
console.log(myObjArray)
}
myFunction();
You can target item number in the array list. You can do statically (i.e. 1-???) or dynamically with an iteration and a variable. You can then the object property within that. For example:
myObjArray[0].info.setTop
That will target the 1st item in the array. Be sure to omit parentheses (()) when passing the method as you want to pass the function reference not the result

Outer Variable scope is not available inside the javascript function

How to access the outer variable inside the inner javascript function , please check my code below i need to access "index" variable inside app() function .
function validate()
{
for (index = 0; index < results.length; index++) {
var parsedData_1;
var provider = results[index].get("provider");
var user = results[index].get("user");
var addresses = user.get("addresses");
var address = addresses[1];
var GameScore = Parse.Object.extend("Address");
var query = new Parse.Query(GameScore);
var data = JSON.stringify(address);
var parsedData = jQuery.parseJSON(data);
query.get(parsedData.objectId, {
success: function(resultadr) {
var res = JSON.stringify(resultadr);
var parsedData_1 = jQuery.parseJSON(res);
var apartment = parsedData_1.apartment;
apa(apartment);
},
error: function(object, error) {
alert('error');
}
});
function apa(apartment)
{
alert(index); [I'm not getting the index value inside this function]
alert(apartment);
}
}
}
Inside the function apa() i need the index count , but im unable to get it , please help how to access the outer value inside the function.
As far as I can see apa() does not have access to the index variable, so I would put it inside the parameter of the function call, and call apa() like this
apa(apartment, index);
The problem is that you are using closures to access the index, thus the lastest value assinged to that variable is accessible in the app function. For example, if results.length equlas 11, index in app function will always be 11.
The soltion is to declare a variable inside the for loop, assign the index value to that variable, and pass the variable to app function.
//Create a factory function for the app function
//Outside the for loop.
var createAppFunc = function (i) {
return function () {
console.log(i);
};
};
for (var index = 0, l = results.length; index < l; index++)
{
var newVar = index;
var app = createAppFunc(index); //Now, app is a function.
}
Good Luck :).
You can use Function.bind() to pass the actual index as first argument to the sucess-callback. There you can get it and pass it along as parameter to function apa(). And: use keyword var for the index in for().
function validate() {
for (var index = 0; index < results.length; index++) {
/* all the vars here */
query.get(parsedData.objectId, {
success: function(idx, resultadr) {
var res = JSON.stringify(resultadr);
var parsedData_1 = jQuery.parseJSON(res);
var apartment = parsedData_1.apartment;
apa(idx, apartment);
}.bind(null, index),
error: function(object, error) {
alert('error');
}
});
function apa(index, apartment) {
console.log(index); console.log(apartment);
}
}
}
The first parameter (here: null) of bind() sets the context of the bound function. Whatever you pass in will be accessible in the success-callback by the keyword this.
I think every time you call the function the call will be compromised by next loop call.. so at last the method will be called only once.
You can declare index variable globally then all the functions have access to it

Keep the "i" value when adding functions to elements

My case:
var tds = document.getElementsByTagName("td");
for(i=0;i<tds.length;i++)
{
tds[i].onclick = function()
{
alert(i);
};
}
Expected outcome: Alert the number of TD.
However if there are 6 TDs, the returned value will always be the last value of "i". (6)
How could i make the "i" value to remain at it's value when added to the function?
Thanks!
http://jsfiddle.net/nuKEK/11/
You need to make a closure to capture the i value. Something like this
function createFunction(i){
return function(){
alert(i);
};
}
var tds = document.getElementsByTagName("td");
for(i=0;i<tds.length;i++){
tds[i].onclick = createFunction(i);
}
DEMO: http://jsfiddle.net/nuKEK/12/
You can pass i to another function in order to get its value rather than a reference to it. In javascript, numbers are passed by value.
tds[i].onclick = (function(x) {
return function() {
alert(x); // alerting x, i's value
};
})(i); // passing i as parameter x
If that self-executing anonymous function looks a little hairy in the context of your loop, you could try Array.prototype.forEach() instead:
[].forEach.call(document.getElementsByTagName("td"), function(td, i) {
td.onclick = function() {
alert(i);
};
});
[edit] Have a look at these options and their performance.
This is one of the common mistakes in Javascript in that it is not block scoped like most languages. It is function-scoped.
You need to create a closure around the onclick to achieve this.
for (i = 0; i < tds.length; i++) {
(function (index) {
tds[index].onclick = function() {
alert(index);
};
})(i);
}
var tds = document.getElementsByTagName("td");
for(i=0;i<tds.length;i++)
{
addClick(tds, i);
}
function addClick(where, i) {
where[i].onclick = function()
{
alert(i);
};
}
You will have to force the value into a scope that will still exist when the callback is fired.
for(i=0;i<tds.length;i++){
(function(){
var _i = i;
tds[i].onclick = function(){
alert(_i);
};
})();
}
Otherwise, the value for i will always be the last index

Passing a function into another function

I have a function that is similar to this:
function foo(array1, fun) {
var n;
n = a.length;
var i;
for (i=0; i<=n; i++) {
fun(a[i]);
}
}
Now I want to create a function called mult(x) that I will pass into foo when I call it. My question is what do I put in the parameters of my mult function when I want to call:
foo(some_array, mult(x));
Just pass in a reference to it (its name only)...
foo(some_array, mult);
Alternatively, pass in an anonymous function...
foo(some_array, function() { ... });
The first argument of this function you pass in with will be set to a[i] like in the body on your function.
Rewritten to showcase how you call a function in JS
function mult(x){
//do stuff to x
}
function foo(array1, fun){
var n = array1.length;
var i;
for (i=0; i<=n; i++) {
mult(array1[i]);
}
}

javascript: Using the current for-loop counter-value inside a function() { }?

on a website i want to do this: (simplified)
myHandlers = new Array();
for(var i = 0; i < 7; i++) {
myHandlers.push(new Handler({
handlerName: 'myHandler'+i, // works, e.g. ->myHandler1, 2, 3 etc.
handlerFunc: function(bla) { /*...*/ alert(i); } // doesn't work,all return 7
}
}
I could set the counter as another attribute of my Handler (which would copy the current value) and use it inside my function, but I guess, there is also a way to actually copy this value, no?
When handlerFunc is called, the i inside the function refers to the i of the for loop. But that i does probably not have the same value any more.
Use a closure to bind the current value of i in the scope of an anonymous function:
handlerFunc: (function(i) { return function(bla) { /*...*/ alert(i); }; })(i)
Here an anonymous function (function(i) { … })(i) is used and called immediately. This function binds the value of i of the for loop to the local i. That i is then independent from the i of the for loop.
var myHandlers = new Array();
for (var i = 0; i < 7; i++) {
myHandlers.push(new Handler({
handlerName: 'myHandler'+i, // works, e.g. ->myHandler1, 2, 3 etc.
handlerFunc:
(function(i) {
return function(blah) {
alert(i)
}
})(i)
}))
}
Use a closure to bind the i so the value stays intact
In your example, i in the functions is the same variable as i outside the functions. As i is incremented in the loop, so is it incremented within the functions. As a result, if the functions are called after the loop has finished, they will all alert "7".
You need to create a new variable with appropriate scope and copy the value of i into it.
Something like this would create the desired effect.
...
var pushHandler = function(i) {
myHandlers.push(new Handler({
handlerName: 'myHandler'+i, // works, e.g. ->myHandler1, 2, 3 etc.
handlerFunc: function(bla) { /*...*/ alert(i); } // doesn't work,all return 7
}
}
...
for(var i = 0; i < 7; i++) {
pushHandler(i);
}
...

Categories

Resources