This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Javascript infamous Loop issue? [duplicate]
(5 answers)
Closed last month.
The following piece of code will produce 1, 2, 3, 4
const array = [1, 2, 3, 4];
for (let i = 0; i < array.length; i++) {
setTimeout(() => {
console.log(array[i]);
}, 1000);
}
Whereas using var i = 0 in the for loop will produce undefined, undefined, undefined, undefined
const array = [1, 2, 3, 4];
for (var i = 0; i < array.length; i++) {
setTimeout(() => {
console.log(array[i]);
}, 1000);
}
I understand var and let have different scopes but can somebody explain why in the var example, i evaluates to 4 in each iteration?
Related
This question already has answers here:
What is the difference between ( for... in ) and ( for... of ) statements?
(18 answers)
Closed 2 years ago.
I'm trying to write a function (onlyOddNumbers) that accepts an array of numbers and returns a new array with only the odd numbers, it's working but the problem is I'm getting strings in the new array instead of numbers, why this happen ?
let oddNumbersOnly=[]
const filter = function (numbers) {
for (number in numbers){
if(number %2 !==0){
oddNumbersOnly.push(number)
}
} return oddNumbersOnly;
};
use for of instead of for in then convert your num to string
const filter = function(numbers) {
let oddNumbersOnly = []
for (let number of numbers) {
if (number % 2 !== 0) {
oddNumbersOnly.push(number.toString())
}
}
return oddNumbersOnly;
};
const arr = [1, 2, 3, 4, 5, 6];
const result = filter(arr)
console.log(result)
let num = [0, 1, 2, 3, 4, 5, 6];
let oddNumbersOnly = num.filter(numb=>numb%2 !==0);
console.log(oddNumbersOnly);
javaScript has an inbuilt es6 filter function. It is shorter and retain the datatype. You may try this.
This question already has answers here:
Merge Two Arrays so that the Values Alternate
(6 answers)
Closed 2 years ago.
How can I merge two arrays in a functional programming approach?
Current
const result = [];
for (let i = 0; i < arr1.length; ++i) {
result.push(arr1[i]);
if (i < arr1.length - 1) {
result.push(arr2[i]);
}
}
This works for I need it to do, but I’d like to see thoughts on my question. I have attempted a few different ways but this is what I think is the cleanest.
function alternatePush (arr1, arr2) {
let myArray = [];
for (let i = 0; i < arr2.length; i++){
myArray.push(arr1[i]);
myArray.push(arr2[i]);
}
return myArray;
}
alternatePush ([1, 3, 5], [2, 4, 6]);
This question already has answers here:
Check if an array contains any element of another array in JavaScript
(32 answers)
Closed 4 years ago.
As per question title, I'm using:
Array.prototype.containsAny = function (otherArray) {
for (let i = 0; i < otherArray.length; i++)
if (this.includes(otherArray[i]))
return true;
return false;
};
let a1 = [3, 5, 9];
let a2 = [4, 5];
a1.containsAny(a2);
Is there a better way?
You can use some and includes.
let a1 = [3, 5, 9];
let a2 = [4, 5];
function containsAny(a1,a2){
return a1.some(e=> a2.includes(e))
}
console.log(containsAny(a1,a2))
console.log(containsAny(a1, [1,2]))
This question already has answers here:
How to count certain elements in array?
(27 answers)
Closed 4 years ago.
input: arbitrary array
output: unique elements and their count
So far I was able to find the unique elements but I can't figure it out how to correlate them with the count for each element. Any suggestions(without using functions if possible - just started and didn't get to functions yet)?
var arr = [3, 4, 4, 3, 3];
var new_arr = [];
for (i = 0; i < arr.length; i++) {
if (new_arr.includes(arr[i])) {
// pass
} else {
new_arr.push(arr[i]);
}
}
console.log(new_arr);
Use an Object instead of an Array to keep track of the count. The key is the number in question and its value is the count.
Use Array#reduce
const res = [3, 4, 4, 3, 3].reduce((acc,cur)=>{
if(acc[cur]) acc[cur]++;
else acc[cur] = 1;
return acc;
}, {});
console.log(res);
Or without any methods:
var arr = [3, 4, 4, 3, 3];
var new_arr = {};
for (i = 0; i < arr.length; i++) {
if (new_arr[arr[i]]) {
new_arr[arr[i]]++;
} else {
new_arr[arr[i]] = 1;
}
}
console.log(new_arr);
This question already has answers here:
Javascript SetTimeout and Loops [duplicate]
(3 answers)
How do JavaScript closures work?
(86 answers)
Closed 8 years ago.
I know that this problem is related to JS scope and I have searched, but can't get the solutions from other stackoverflow questions to work.
I have this program
http://jsfiddle.net/0z525bhf/
function write(x, y) {
console.log(x);
console.log(y);
}
var data = {
"property": {
"1": {
"values": [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
},
"2": {
"values": [[11, 12], [13, 14], [15, 16], [17, 18], [19, 20]]
}
}
}
var delay = 1000;
for (var x in data.property) {
for (var i = 0; i < data.property[x].values.length; i++) {
var one = data.property[x].values[i][0];
var two = data.property[x].values[i][1];
setTimeout(function() {
write(one, two);
}, delay);
delay += 1000;
}
}
that reads data from an object and loops over both the object and the arrays in it. I want it to print the array values one second apart, but it always prints the values from the last iteration. I have tried with closures as suggested in the other question, but can't get it to work.
In the specific case of setTimeout, you don't even need a closure. You can pass variables to the timeout function, as follows:
for (var x in data.property) {
for (var i = 0; i < data.property[x].values.length; i++) {
var one = data.property[x].values[i][0];
var two = data.property[x].values[i][1];
setTimeout(function(one, two) {
write(one, two);
}, delay, one, two);
delay += 1000;
}
}
You could have applied you own research and used the following method.
for (var i = 0; i < data.property[x].values.length; i++) {
(function (one, two) {
setTimeout(function() {
write(one, two);
}, delay);
})(data.property[x].values[i][0], data.property[x].values[i][1]);
delay += 1000;
}
Working jsfiddle: http://jsfiddle.net/0z525bhf/1/
That's a problem with lexical closures : the function you pass to setTimeout closes over the variables one and two which get modified during iteration. This is why you should never declare a function in the body of a for loop.
Using a functional loop will solve it :
var delay = 1000;
for (var x in data.property) {
data.property.value[x].forEach(function (tuple) {
var one = tuple[0], two = tuple[1];
setTimeout(function() {
write(one, two);
}, delay);
delay += 1000;
});
}