Workaround for let keyword? - javascript

How can I get this
var i = 0;
var codes = [1, 2, 3];
for (var i = 0; i < codes.length; ++i)
{
setTimeout(function(){alert(codes[i]);},100);
}
To alert 1, 2 and 3 without using let keyword?
or bind an event on an element (example):
var i = 0;
var codes = [1, 2, 3];
for (var i = 0; i < codes.length; ++i)
{
$("div").eq(i).click(function(){
alert( codes[i] );
});
}

Use a self-executing anonymous function and pass in i as an argument for variable closure.
var i = 0;
var codes = [1, 2, 3];
for (var i = 0; i < codes.length; ++i)
{
(function( index ) {
setTimeout(function(){alert(codes[index]);},100);
})(i);
}
Here's an example.

You need to make use of a closure. I typically create a "generator" function that returns a function which is defined in the desired context:
var i = 0;
var codes = [1, 2, 3];
function callbackGenerator(i) {
return function(){alert(codes[i]);}
}
for (var i = 0; i < codes.length; ++i)
{
setTimeout(callbackGenerator(i), 100);
}
More info and good examples here:
https://developer.mozilla.org/en/JavaScript/Guide/Closures

var i = 0;
var codes = [1, 2, 3];
var timeoutFunc = function() {
alert(codes[i++]);
if (i < codes.length) {
setTimeout(timeoutFunc, 100);
}
};
setTimeout(timeoutFunc, 100);

This should do it.
var codes = [1, 2, 3];
for (var i = 0; i < codes.length; ++i)
setTimeout(function(code){return function(){
alert(code);
}}(codes[i]), 100);

Use a self-executing function:
for (var i = 0; i < codes.length; ++i) (function(bound_i) {
setTimeout(function(){alert(codes[bound_i]);},100);
})(i);
Optionally using a var statement for more verbose code:
for (var i = 0; i < codes.length; ++i) (function() {
var bound_i = i;
setTimeout(function(){alert(codes[bound_i]);},100);
})();
Or use a named function instead if you want to:
function foo(i) {
setTimeout(function(){alert(codes[i]);},100);
}
for (var i = 0; i < codes.length; ++i) {
foo(i);
}
Either example forms a closure, which introduces new variable scope. Alternatively, ES5 has Function.bind that could be used on the anonymous function, but it is not universally supported in all browsers yet. (I'm thinking of IE.)

Related

Javascript forEach Loop

Trying to make this function true. I think the problem is in my for loop.
function forEach(array, callback){
console.log(array, callback);
for(var i = 0; i < array.length; i++) {
}
}
// testing your code with console.assert
var total = 1;
var myArray = [1, 2, 3, 4];
function multiplyTotal(a) {
total *= a;
}
forEach(myArray, multiplyTotal);
// and finally assert; if this fails, the program stops
console.assert(total === 24);
function forEach(array, callback){
console.log(array, callback);
for(var i = 0; i < array.length; i++) {
callback(array[i]); // you need to call callback function
}
}
Additionally, Javascript already has a built in function for this:
myArray.forEach(multiplyTotal);
http://www.w3schools.com/jsref/jsref_forEach.asp

Simple Javascript for loop hangs browser

This Javascript hangs browser when the number of iteration is set to 5. However, if set to 4, it runs normally. What is the problem?
var sample = [
[1,2,3],
[4,5,6],
[7,8,9]];
for(i = 0; i < 5; i++)
swapColumn(sample, 0, 1);
function swapColumn(array, x, y)
{
for(i = 0; i < array.length; i++)
{
temp = array[i][x];
array[i][x] = array[i][y];
array[i][y] = temp;
}
}
Don't forget to use var to declare variables
var sample = [
[1,2,3],
[4,5,6],
[7,8,9]];
for(var i = 0; i < 5; i++)
swapColumn(sample, 0, 1);
function swapColumn(array, x, y)
{
for(var i = 0; i < array.length; i++)
{
var temp = array[i][x];
array[i][x] = array[i][y];
array[i][y] = temp;
}
}
Otherwise they are treated as global variables, and you are actually overwriting i everytime you enter swapColumn

Can't get inside my for loop (Javascript)

I am trying to iterate over the variable pieces, but somehow it is not triggering. In the function below, pieces.length turns 4, but piecesNew turns [] - moreover console.log(i) is never reached.
What is happening?
self.reworkPieces = function(pieces) {
var piecesNew = [];
console.log(pieces.length)
for (var i; i <= pieces.length; i++) {
console.log(i)
piecesNew[i] = {
c: pieces[i].r,
r: pieces[i].c,
p: i
}
}
console.log(piecesNew)
return piecesNew;
};
undefined is not less than or greater than any number.
var i; // undefined
i < 10; // false
i > 10; // false
You simply need to make sure i is equal to 0.
You also want i to never be equal to pieces.length so use < instead of <= (the last index of an array is always length - 1, e.g. an array of length 3 has indexes 0, 1 and 2 – the first index is always 0, not 1)
So:
for (var i = 0; i < pieces.length; i++) {
...
define value for variable i, var i = 0
self.reworkPieces = function(pieces) {
var piecesNew = [];
console.log(pieces.length)
for (var i = 0; i <= pieces.length; i++) {
console.log(i)
piecesNew[i] = {
c: pieces[i].r,
r: pieces[i].c,
p: i
}
}
console.log(piecesNew)
return piecesNew;
};
self.reworkPieces = function(pieces) {
var piecesNew = [];
console.log(pieces.length)
for (var i = 0; i <= pieces.length; i++) {
console.log(i)
piecesNew[i] = {
c: pieces[i].r,
r: pieces[i].c,
p: i
}
}
console.log(piecesNew)
return piecesNew;
};
Change:
for (var i; i <= pieces.length; i++)
To:
for (var i = 0; i < pieces.length; i++)
Initialize var i = 0 initially then it will work
self.reworkPieces = function(pieces) {
var piecesNew = [];
console.log(pieces.length)
for (var i = 0; i <= pieces.length - 1; i++) {
console.log(i)
piecesNew[i] = {
c: pieces[i].r,
r: pieces[i].c,
p: i
}
}
console.log(piecesNew)
return piecesNew;
};

Moving code inside a function is not working

Any help will be very appreciated... I am trying to figure out how to nest loops inside of a function. If I input this into the console...
var i, arr = [1, 2, 3, 4, 5, 6];
var remove = [];
for (i = 0; i < arr.length; i++) {
if (Number(arr[i]) != i % 2) {
remove.push(arr[i]);
arr.splice(i, 1);
}
}
console.log(remove);
it returns with the desired array, removing all the even numbers from arr. But, if I wrap it in a function, it is undefined...
var i, arr = [1, 2, 3, 4, 5, 6];
var remove = [];
function reject() {
for (i = 0; i < arr.length; i++) {
if (Number(arr[i]) != i % 2) {
remove.push(arr[i]);
arr.splice(i, 1);
}
}
};
console.log(remove);
What am I doing wrong?
When code is not in a function, every line in the script is executed as it is interpreted (roughly speaking).
If you wrap some code inside a function, you have to call the function for it's effects to be applied.
Also, you should try and keep some variables inside the function, for example your i counter could be local to the function instead of the global scope of the function.
Therefore, use the function name to apply it's effects:
var arr = [1, 2, 3, 4, 5, 6];
var remove = [];
function reject() {
var i;
for (i = 0; i < arr.length; i++) {
if (Number(arr[i]) != i % 2) {
remove.push(arr[i]);
arr.splice(i, 1);
}
}
};
reject(); // Difference here, we're calling the function.
console.log(remove);
You need to call the function before you try to log the value of remove.
var i, arr = [1, 2, 3, 4, 5, 6], remove = [];
function reject() {
for (i = 0; i < arr.length; i++) {
if (Number(arr[i]) != i % 2) {
remove.push(arr[i]);
arr.splice(i, 1);
}
}
};
reject();
console.log(remove);
Others have already answered what the problem is, you have to call the function. However, if you improve it not to use globals, it may be more obvious that you need to call it and is much cleaner code.
var arr = [1,2,3,4,5];
function reject(input) {
var output = [];
for (var i = 0; i < input.length; i++) {
if (Number(arr[i]) != i % 2) {
output.push(arr[i]);
input.splice(i, 1);
}
}
return output;
};
var remove = reject(arr);

Is it possible to define and initialize multidimensional arrays in JavaScript in one line of code?

Sorry if this is too basic, but I am struggling at defining 4-dimensional array (of size 6x6x6x6) in JavaScript and initializing it to all 1's. What's the easiest way to do this?
Thanks!
You can use the literal syntax, but it would be very big and cumbersome. You may want to try something like this:
var x = [1, 1, 1, 1, 1, 1];
for (var i = 1; i < 4; i++) {
x = [x, x, x, x, x, x];
}
I found a slightly simpler solution:
var x = 1;
for (var i = 0; i < 4; i++) {
x = [x, x, x, x, x, x];
}
Seems like there should be easier way, but this will do it.
var array = [];
for(var i=0; i<6; i++) {
for(var j=0; j<6; j++) {
for(var k=0; k<6; k++) {
for(var l=0; l<6; l++) {
array[i][j][k][l]=1;
}
}
}
}
Edit
To generate an n-dimensional AxBxCxDx... array (untested):
Array.prototype.fill = function(elem, n) {
for(var i=0; i<n; i++, this.push(elem));
}
function generateArray() {
var dimensions = Array.prototype.slice.call(arguments);
var x = 1;
for (var i = dimensions.length-1; i >= 0; i--) {
x = [].fill(x, dimensions[i]);
}
return x;
}
to generate a 2x3x4x5 matrix:
generateArray(2,3,4,5);
I implemented ddlshack's generalized method, but ran into an issue due to the fact that arrays are "pass by reference" in JavaScript. This resulted in each dimension of the array holding multiple references to the same array rather than copies of it. To correct the issue, I implemented the solution as follows (the only other difference being that I used a second function rather than modify Array's prototype).
var fillArray = function(val, dim) {
var a = [];
for (var i = 0; i < dim; i++) {
if (Object.prototype.toString.call(val) === "[object Array]") {
val = val.slice(0);
}
a.push(val);
}
return a;
};
var generateArray = function() {
var dimensions = Array.prototype.slice.call(arguments),
val = 0;
for (var i = (dimensions.length - 1); i >= 0; i--) {
val = fillArray(val, dimensions[i]);
}
return val;
};

Categories

Resources