Outer Variable scope is not available inside the javascript function - javascript

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

Related

function is overriding variable declared in other scope

I have to functions both using i as an iterator.
One function is using the other.
I thought local Variables cant be changed by other scopes.
But now "i" is changed after the "createOptions" function.
Is it possible that the value is passed by the object?
function createOptions(array) {
var optionArray = [];
for (i=0;i<array.length;i++) {
var option = $("<option></option").text(array[i]);
$(option).attr("value", array[i]);
optionArray.push(option);
}
return optionArray;
}
function buildForm(players) {
var form = $("<form></form>");
for (i=0; i<4; i++) {
var playernumber = "player " + (i+1).toString();
var select = $("<select></select>").attr({
"id" : playernumber,
"onchange" : "addNewPlayer(this)"
});
var selectPlayerOption = $("<option></option>").text("-- select Player --");
$(selectPlayerOption).attr({
"disabled" : true,
"selected" : true
})
var newPlayerOption = $("<option></option>").text("New Player");
var playerOptions = createOptions(players);
console.log(playerOptions.j);
$(select).append(selectPlayerOption, newPlayerOption, playerOptions);
$(form).append(select);
}
$("#maincontent").append(form);
}
If you create the variable like i = 0 even if it is inside a for loop still will be created as global variable.
Suggested way instead:
for (let i=0; i < array.length; i++) {
// your code
}
Read further here about let.
I hope that helps!
that is normal your function buildForm is using i as an iterator and when CreateOption is called inside buildForm function it value is reassigned to 0 because of this line for (i=0;i<array.length;i++) in createOption function.
So unless you want to use i in both functions i suggest to use two differents iterators i and j for example

Using callback's returned value as an argument to another function

I have referenced multiple SO questions but I still could not find a solution. These are the questions I took a look at (main ones):
Pass a JavaScript function as parameter
How to execute a method passed as parameter to function
compute.js:
const mainTable = document.getElementById('nonFixedSample');
function getRows(metricName) {
let row = 0;
let z = document.getElementsByTagName('tr');
for (let i = 0; i < z.length; i++) {
if (mainTable.rows[i].firstChild.textContent === metricName) {
row = i;
return row;
}
}
}
// Here I am trying to pass that function as callback
function stdCellArea(callback) {
rowNumber = callback();
let runs = mainTable.rows[rowNumber].cells.length;
// Other code
}
Now I am calling it, reg_report.php:
<script>
stdCellArea(function() {
getRows('test');
});
</script>
But I get the following error:
Uncaught TypeError: Cannot read property 'cells' of undefined
at stdCellArea (compute.js:17)
at reg_report.php:39
Basically, I need to use return value of getRows() as an argument for stdCellArea(). I know I could simply do this:
let x = getRows('text');
stdCellArea(x);
But I have to call this function over 10 times, so I do not want to create many variables. Who can help?
You need to return the value from your callback: return getRows('test');. Without that, rowNumber becomes undefined as that's what functions without an explicit return, return.

Call a returned function from outside its function

I'm trying to call a function that's returned from a function. Here's what I mean:
myFunction.something; // (Wrong)
function myFunction() {
return {
something: function() {
...
}
};
}
When I try calling myFunction.something nothing happens. How can I call a returned function outside of its function?
JSFiddle
var index = 0;
var animID = requestAnimationFrame(myFunction.something);
function myFunction() {
return {
something: function() {
index++;
console.log(index);
if (index === 5) cancelAnimationFrame(animID);
else animID = requestAnimationFrame(myFunction.something);
}
};
}
I would first of all recommend using descriptive variable names; utils rather than myFunction, and incrementFrame rather than something, for example. I would second of all recommend reconsidering your approach to code organization and simply putting all of your helper functions directly in an object, then referencing that object:
var index = 0;
var animID = requestAnimationFrame(utils.incrementFrame);
var utils = {
incrementFrame: function() {
index++;
console.log(index);
if (index === 5) cancelAnimationFrame(animID);
else animID = requestAnimationFrame(utils.incrementFrame);
}
}
There are a few differences between these approaches, some of them frustratingly subtle. The primary reason I recommend using an object for organization rather than a function which returns an object is because you don't need to use a function for organization; you are unnecessarily complicating your code.
myfunction is not the object that you get from calling myfunction(), it's the function itself and does not have a .something method.
You could call it again (as in myfunction().something()), but a better approach would be to store a reference to the object you've already created:
function myFunction() {
var index = 0;
var o = {
something: function() {
index++;
console.log(index);
if (index < 5) requestAnimationFrame(o.something);
// btw you don't need to cancel anything once you reach 5, it's enough to continue not
}
};
return o;
}
myFunction().something();
Alternatively you might want to drop the function altogether, or use the module pattern (with an IIFE), as you seem to use it like a singleton anyway.
Try this:
myFunction().something()
myFunction() calls the myFunction function
them we use the dot notation on the returned value (which is an object) to find the something member of it
that member is a function too, so add another set of brackets () to call it
Call function after writing it
var index = 0;
function myFunction() {
return {
something: function() {
index++;
console.log(index);
if (index === 5) cancelAnimationFrame(animID);
else animID = requestAnimationFrame(myFunction().something);
}
};
}
var animID = requestAnimationFrame(myFunction().something);

variable closure using jQuery object notation

I have the following:
for (var i = 0; i <= 10; i += 1) {
var $page_button = $('<a>', {
html : i,
click : function () {
var index = i;
console.log(index);
return false;
}
});
$page_button.appendTo($wrapper);
}
I thought that var index would be defined separately for each iteration of the loop because it is enclosed within a function. In this case the value of index that is printed is always 10.
The link text is the correct value of i, because this is written to the DOM and is then immutable .
Why is this, and what should I change to fix my problem?
I know this is similar to lots of other questions but the behaviour of using this notation is causing a different result. I am using jQuery 1.7.2 (Can't use any newer unfortunately.)
You need to enclose that in a closure to solve the problem..
var $page_button = $('<a>', {
html : i,
click : (function (num) {
return function(){
var index = num;
console.log(index);
return false;
}
})(i)
});
A reference to i is closed up as part of the anonymous function. Note: not to its value, but a reference to i itself. When the function is run, the value is evaluated. Because the function runs after the loop has ended, the value will always be the last value of i. To pass just the value around, you do something like this:
click : (function (index) {
return function () {
console.log(index);
return false;
};
})(i)
You create an anonymous function which you execute immediately, which takes a value as argument and returns your actual function.
The variable index is defined separately for each execution of the function, but you copy the value from the variable i inside the function, so you will use the value of i as it is when the function runs, not when the function is created.
You need a function that is executed inside the loop to capture the value of the variable:
for (var i = 0; i <= 10; i += 1) {
(function(){
var index = i;
var $page_button = $('<a>', {
html : i,
click : function () {
console.log(index);
return false;
}
});
})();
$page_button.appendTo($wrapper);
}
Every handler is sharing the same i variable. Each one needs its own variable scope in order to reference a unique index.
for (var i = 0; i <= 10; i += 1) {
var $page_button = $('<a>', {
html : i,
click : makeHandler(i) // invoke makeHandler, which returns a function
});
$page_button.appendTo($wrapper);
}
function makeHandler(index) {
return function () {
console.log(index);
return false;
};
}
Here I made a makeHandler function that accepts the index argument, and returns a function that is used as the handler.
Because a function invocation sets up a new variable scope, and because a function is created and returned inside the makeHandler, each handler returned will reference its own scoped index number.

Arguments to JavaScript Anonymous Function

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);
}
}

Categories

Resources