Setting a constant in a javascript function [duplicate] - javascript

This question already has answers here:
JavaScript for loop index strangeness [duplicate]
(3 answers)
Closed 9 years ago.
Take a look at this code:
var arr = new Array();
for (var i = 0; i < 10; i++) {
arr[i] = {
func:function() {
console.log(i);
}
}
}
arr[0].func();
I am confused by this, because I thought this would work. I basically would like each object in the array to print the value it was given when the function was created.
Right now when I call func(), it prints 10 in the console. Is there a way to make it print 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 instead? Thanks!

The problem is that the function inside is referencing the variable 'i' which increases every time. You can store the value of 'i' in each iteration in the object alongside the function like this:
http://jsfiddle.net/Sgnvp/
var arr = new Array();
for (var i = 0; i < 10; i++) {
arr[i] = {
func:function() {
console.log(this.value);
},
value: i
}
}
arr[0].func();

You have to create a closure to encapsulate the value. Here I'm calling consoleIt and passing it i. consoleIt creates a closure around the i
var arr = [];
function consoleIt (i) {
return function () {
console.log(i);
}
};
for (var i = 0; i < 10; i++) {
arr[i] = {
func: consoleIt(i)
};
}
arr[0].func();

This is no better really than the way that thebreiflabb did it, but it's an interesting technique that's worth knowing:
var arr = [];
for (var i = 0; i < 10; i++){
(function(i){
arr[i] = {
func : function(){
console.log(i);
}
};
})(i);
}
arr[0].func();
It just uses an anonymous closure to scope i.

Related

Can't get i from for ((i = 0; i < koniec.length; i++) to index thru console.log(silnia(5)[i]);

In my JS script, I am trying to index thru silnia() a function that returns an array, I can do that manually without a problem: silnia(5)[1] but when I try to use an i from a for-loop it does not work.
koniec = [1,2,3];
for (i = 0; i < koniec.length; i++){
// Returns only undefined:
console.log(silnia(5)[i]);
// Works no problem:
// console.log(silnia(5)[2]);
}
function silnia(n){
var wynikSilni = [];
for(i = 1; i < (n + 1); i++){
wynikSilni.push(i);
}
return wynikSilni;
}
You're not using a var, let or const statement to declare i, so it is considered a global variable.
Which means the same i you use in the silnia function is the same i being used in the for loop outside of it; essentially, the loop outside of it runs once, the silnia increments i to 6, and once it returns to the for loop in global scope, it stops because i>koniec.length (ETA: It then tries to access sylnia(5)[6] because i equals 6 at that point in time, which is undefined)
Try this:
function silnia(n) {
var wynikSilni = [];
for (var i = 1; i < (n + 1); i++) {
wynikSilni.push(i);
}
return wynikSilni;
}
koniec = [1, 2, 3];
for (var i = 0; i < koniec.length; i++) {
// Returns only undefined:
console.log(silnia(5)[i]);
// Works no problem:
// console.log(silnia(5)[2]);
}
It's 2019 and Arrays have quite a few helpful methods that eliminate the need to set up and manage loop counters, which as others have pointed out, is the source of your problem.
Array.forEach() is the simplest of these and will help to greatly simplify your issue:
koniec = [1,2,3];
// Loop over the knoiec array
// .forEach requires a callback function to execute
// upon each loop iteration. That function will automatically
// be passed 3 arguments: the array item, the item index, the array
koniec.forEach(function(item, index){
console.log(silnia(5)[index]);
});
function silnia(n){
var wynikSilni = [];
for(i = 1; i < (n + 1); i++){
wynikSilni.push(i);
}
return wynikSilni;
}
You need to declare the variables, otherwise you use global variables for all functions.
function silnia(n) {
var wynikSilni = [];
for (var i = 1; i < (n + 1); i++) { // use var or let
wynikSilni.push(i);
}
return wynikSilni;
}
var koniec = [1, 2, 3];
for (var i = 0; i < koniec.length; i++) { // use var or let
console.log(silnia(5)[i]);
}

Confused about function closures

Can someone please explain why does it console log out 10, 10, 10 instead of 9, 9, 9?
When it goes through for loop shouldn't it stop at 9?
var foo = [];
for (var i = 0; i < 10; i++) {
foo[i] = function() {
return i;
};
};
console.log(foo[0]());
console.log(foo[1]());
console.log(foo[2]());
Whenever any function which is using any variable from parent scope is executed, it gets that value of a variable which it is holding at the time of function execution. In your case i is already reached to 10 at the time of execution because of i++.
For getting expected result, you can add IIFE to it, which will hold the value of i in its scope.
var foo = [];
for (var i = 0; i < 10; i++) {
foo[i] = (function(i) {
return function() {
return i;
};
})(i);
};
console.log(foo[0]());
console.log(foo[1]());
console.log(foo[2]());
You can use this syntax which keeps the context
for (let i = 0; i < 10; i++) {
foo[i] = () => i;
};
console.log(foo[0]());
console.log(foo[1]());
console.log(foo[2]());
https://jsfiddle.net/bandpay/8zat3bnn/

How to check the index of a function in an Array of functions in JavaScript [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 5 years ago.
I am pretty new level to JavaScript.
I have a function taking y as the input to return an array with size y which has almost the same functions as the elements.
This is my code:
function createArrayOfFunctions(y) {
var arr = [];
for(var i = 0; i<y; i++) {
arr[i] = function(x) {
return x + i);} //Probably this is the issue
}
return arr;
}
var input = "5,3,2";
var [y, n, m] = input.split(",");
console.log("input = " + input);
[y, n, m] = [parseInt(y), parseInt(n), parseInt(m)]
var addArray = createArrayOfFunctions(y);
console.log(addArray[n](m)); //I would like to add up n and m
When I execute the code, the i keeps at 5 instead of iterating from 0,1,2,3,4 for arr[0],arr[1],arr[2],arr[3],arr[4]. As a result, it always output m+y instead of n+m. I have tried to use indexOF and this[i] to figure out the index of the functions, but it does not work. Is there any ways for me to do this?
Thanks!
You've encountered a scoping issue.
Here is a solution:
function createArrayOfFunctions(y) {
let arr = [];
for (let i = 0; i < y; i++) {
arr[i] = function(x) {
return x + i;
};
}
return arr;
}
The above uses let, which scopes the i variable to each loop iteration.
If you can't use let due to compatibility, use an IIFE for each loop:
function createArrayOfFunctions(y) {
var arr = [];
for (var i = 0; i < y; i++) {
(function() {
var _i = i;
arr[_i] = function(x) {
return x + _i;
};
})();
}
return arr;
}
The above code caches each i variable for each loop in an IIFE, which keeps it in scope.

Creating a frequency listing of characters

charFreq function that's not quite working out. Hit a wall. I know I may need to
do a conditional. Calling the function returns an Object error. I'm attempting
to get string into an empty object displaying the characters like this - Object
{o: 4, p: 5, z: 2, w: 4, y: 1…}. New to Javascript by the way.
Just realized I shouldn't be appending anything. Do I need to do a .push() to
push the array into the object?
function charFreq (string){
var emptyObj = {};
for(var i = 0; i < string.length; i++) {
// console.log(string.charAt(i));
var args = [string.charAt(i)];
var emptyArr = [''].concat(args);
emptyObj += emptyArr
}
return emptyObj
}
undefined
charFreq('alkdjflkajdsf')
"[object Object],a,l,k,d,j,f,l,k,a,j,d,s,f"
You just need to set emptyObj's key of that specific letter to either 1 if it doesn't exist or increment the count if it already does.
function charFreq(string) {
var obj = {};
for (var i = 0; i < string.length; i++) {
if (!obj.hasOwnProperty(string[i])) {
obj[string[i]] = 1;
} else {
obj[string[i]]++;
}
}
return obj;
}
console.log(charFreq('alkdjflkajdsf'));
Try this instead: you need to create an object property first, then increment it. What you do, is implicitly convert the object to a string and concatenate more string data to it (using += and concat).
This is a simple approach:
function charFreq(string){
var emptyObj={};
for(var i=0; i<string.length; i++) {
if(!emptyObj.hasOwnProperty(string[i])){ // if property doesn’t exist
emptyObj[string[i]]=0; // create it and set to 0
}
emptyObj[string[i]]++; // increment it
}
return emptyObj;
}
A modified version of Richard Kho's code:
function charFreq(string) {
var obj = {};
for (var i = 0; i < string.length; i++) {
var c=string[i];
if (c=='') continue;
if (obj[c]==null) obj[c]=0;
obj[c]++;
}
return obj;
}

Typescript get i value on a callback function when created

How can obtain the current value of i ?
var array = [1, 2, 3];
for (var i = 0; i < array.length; i++)
{
$(element).load("http://www.google.de", () => {
console.log(i);
}
}
Will return 2, 2, 2... How can i return 0, 1, 2 ?
It is because you are using a closure variable i from the outer function inside the ajax callback. Any changes made in the variable value will get reflected in the callback method.
One possible way is to use an anonymous function to provide a custom closure as given below
for (var i = 0; i < array.length; i++)
{
(function(i){
$(element).load("http://www.google.de", () => {
console.log(i);
}
})(i)
}

Categories