access object variable from method javascript - javascript

i have a problem accessing an array within an object method.
While the log returns the value perfectly, the following line returns an error that allRect[n] is undefined.
I suppose it has something to do with variable accessibility, but the fact that it can be logged in one line and refuses it's existence in the next one leaves me a bit out of ideas.
Thanks all.
this.s = Snap('#'+id);
var allRects = [];
this.xPos = 0;
var scale = vizWidth/locationSum(data);
...
//methods
this.updateViz = function() {
apiRequest('datasets', 164, 'json').done(
function(data){
var n = 0;
data = locationDataIntoArray(data);
for(i = 0; i< allRects.length; i++){
console.log(allRects[n]);
allRects[n].animate({ width:parseInt(data[i][2]), opacity:evaluateMachine(data[i][0])},3000);
n++;
allRects[n].animate({ width:parseInt(data[i][3]), opacity:evaluateTech(data[i][1])},3000);
n++;
}
}
)
};

In this code:
for(i = 0; i< allRects.length; i++){
console.log(allRects[n]);
allRects[n].animate({ width:parseInt(data[i][2]), opacity:evaluateMachine(data[i][0])},3000);
n++;
allRects[n].animate({ width:parseInt(data[i][3]), opacity:evaluateTech(data[i][1])},3000);
n++;
}
you're incrementing n twice on each iteration. Halfway through the for loop, n will be beyond the end of the array.
The first time through the loop, when i and n are both zero, you'll animate allRects[0]. Then you increment n and animate allRects[1], and then increment n again. Thus, on the second time through the loop, you'll be animating allRects[2] and allRects[3], and so on.

Related

jQuery: passing variable to function declared inside for loop [contesting duplicate]

I ask this question again as user Cerbrus have marked the previous question as a duplicate of this question.
Can someone be so kind to show me how the question indicated by this user, should solve the code below? I can't find a match between those situations (even thought they are similar).
I need to pass a variable to a function inside a for loop. Here's an example:
var mainObj = [],
subArr = ['val1', 'val2'],
tmp;
for (var i = 0; i < subArr.length; i++) {
tmp = subArr[i];
mainObj.push({
key: function(varsFromLibrary) {
myFunc(tmp);
}
});
}
Here I have 2 problems:
why do i have to assign subArr[i] to tmp? Using myFunc(subArr[i]) will return that i is undefined?
why in myFunc i only receive the last value of subArr array?
UPDATE
I've updated the code as follows but i get TypeError: funcs[j] is not a function
var mainObj = [],
subArr = ['val1', 'val2'],
tmp,
funcs = [];
function createfunc(i) {
return function() { console.log("My value: " + i); };
}
for (var i = 0; i < subArr.length; i++) {
funcs[i] = createfunc(subArr[i]);
}
for (var j = 0; j < subArr.length; j++) {
tmp = subArr[i];
mainObj.push({
key: function(varsFromLibrary) {
funcs[j]();
}
});
}
Simply use let :
for (var i = 0; i < subArr.length; i++) {
let tmp = subArr[i];
mainObj.push({
key: function(varsFromLibrary) {
myFunc(tmp);
}
});
}
Or why cant you simply copy the value into the object?:
for (var i = 0; i < subArr.length; i++) {
mainObj.push({
tmp:subArr[i],
key: function(varsFromLibrary) {
myFunc(this.tmp);
}
});
}
Another try of explaining:
Lets imagine youre a byciclist. You want to measure your speed so you ask 10 friends of you to stand next to the route at certain points and to tell you your speed. Some pseudocode:
const friends = [];
var speed = 20;//youre really fast
for(var point = 1; point < 10; point++){
speed -= 2;//youre slowing down
friends.push({
ask(){
console.log(point, speed);
}
});
}
Now afterwards you stand at the last point 10 together with your friends and you ask them for the current speed and the point they stay at. What will they tell you? Exactly, they are all standing next to you at point 10 and your current speed is 0. You asked them for the current speed and not to remember the current speed. If you want them to remember it, they need to write it down:
friends.push({
speed,//every friend object has the current value stored
point,
ask(){ console.log(this.speed,this.point)}
});
Or you need to create 10 parallel universes your friends stay in, so if you ask them for your speed they will still see you driving next to them:
for(let point = 1; point < 10; point++){
let localspeed = (speed -= 2);//youre slowing down
why do i have to assign subArr[i] to tmp?
You don't. That isn't the solution proposed by the duplicate question.
Using myFunc(subArr[i]) will return that i is undefined?
i won't be undefined. It will be the same as subArr.length.
subArr[i] will be undefined, because subArr.length is the number of items in the array and the array is zero indexed.
why in myFunc i only receive the last value of subArr array?
Because that is the last value you copied to tmp before the loop ended.
As the high rated answer on the question you link to says, you need to copy i or subArr[i] to a new scope so it won't change next time you go around the loop.

Evaluating Terminating Condition

I am learning javascript to enhance some of my daily work, and so I am learning the basics.
I am still pretty green with the syntax, but am picking up on the language pretty quickly.
What I am trying to understand is how i can create a terminating condition that is evaluating a function.
I know the coding is wrong here, which is what I am trying to fix - I attempted a bunch of different things, but I am having trouble evaluating the loop based on my product.
I tried using return to store the value each iteration, but every attempt resulted in the script flat out failing.
What I want the script to do is to stop the loop when my product reaches <=100.
The problem is, my research suggests that the loop criteria can ONLY be referencing the variable, i.
I'm stuck in terms of how to look at the resulting product as the terminating condition.
var one = 5;
var two = 10;
var end = 100;
function mult (one, two) {
var product = one * two;
document.writeln(product + "<br>");
}
for (var i = 1; i <= end; i++)
mult(i, two);
If you want your loop to terminate when the product is <= 100, use an if statement to decide whether you want to write a line.
I've changed some variable names to make it easier to understand.
/*var one = 5;*/ /*This is never being used*/
var ten = 10;
var end = 100;
function mult (a, b){
var product = a * b;
if (product <= 100){
document.writeln(product + "<br>");
}
}
for (var i = 1; i <= end; i++){
mult(i, ten);
}
"the loop criteria can ONLY be referencing the variable, i." that's false!
You can define multiple conditions in a for loop.
To access the 'product' variable after loop execution you can declare it in the outer scope of the mult() function (or you can rewrite the mult() function to returns the product variable).
Like this:
var two = 10;
var end = 100;
var someNumberGtThan100 = 100000;
var lastProduct = 0;
var product = 0;
function mult (one, two) {
lastProduct = product;
product = one * two;
document.writeln(product + "<br>");
}
for (var i = 1; i <= someNumberGtThan100 && product <= 100; i++) {
mult(i, two);
}
console.log(lastProduct); // 100
By using this condition you have to store the previous value in an auxiliary variable, because when 'product' reach the value of 100 the loop condition is still true, so the loop will be executed one time more.

Blackjack javascript game infinite loop

I have created an utterly simple blackjack game that stores the first value of a shuffled array of cards into corresponding players' arrays, dealing them as actual hands. For some odd reason, I can't seem to find a way to execute the core part of the code multiple times without getting an infinite loop. For the time being, I have only tried running the quite commonplace "for" command which is meant for multiple statements, but just doesn't seem to work here.
The programm on its primitive form is as follows...
var dealerCards = [];
var playerCards = [];
var firstDeck = [];
function shuffle(o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
function createShuffledDeckNumber(array, x) {
for (i = 0; i < 4*x; i++) {
array.push(1,2,3,4,5,6,7,8,9,10,11,12,13);
}
shuffle(array);
}
function drawCard(playersHand, playerSoft, playerHard) {
playersHand.push(firstDeck[0]);
firstDeck.shift();
}
function checkDeckDrawOne(playersHand) {
if (firstDeck.length === 0) {
createShuffledDeckNumber(firstDeck, 1);
drawCard(playersHand);
}else{
for (i = 0; i < 1; i++) {
drawCard(playersHand);
}
}
}
for (i = 0; i < 4; i++) {
dealerCards = [];
playerCards = [];
checkDeckDrawOne(dealerCards);
checkDeckDrawOne(dealerCards);
checkDeckDrawOne(playerCards);
checkDeckDrawOne(playerCards);
console.log("dealerCards",dealerCards,"playerCards",playerCards);
console.log("firstDeckDrawn", firstDeck, "Number", firstDeck.length);
}
Additional Notes;
The presumed objective could be performing calculations to figure out the winner by imitating the effect of consecutive computing rounds based on a finite number of values stored in each player's array. Although, I've tried a seried of different things when it comes to emulating the real life circumstances of actually playing blackjack, this version seems to do just that, by also giving the programmer the ability to introduce counting systems like KO or HiLo. The main logic behind the whole thing is fairly simple; order x shuffled decks whenever a command that involves drawing a card is being executed unless the deck has at least one card.
It's rather fair to ponder why should I possibly bother creating multiple rounds in such a game. Reason is, that I want to create an autoplayer application that provides me with percentages on processed data.
Your variable i in function checkDeckDrawOne() has global scope, meaning it alters the value of i in the main loop:
for (i = 0; i < 4; i++) {
dealerCards = [];
playerCards = [];
checkDeckDrawOne(dealerCards);
checkDeckDrawOne(dealerCards);
checkDeckDrawOne(playerCards);
checkDeckDrawOne(playerCards);
console.log("dealerCards",dealerCards,"playerCards",playerCards);
console.log("firstDeckDrawn", firstDeck, "Number", firstDeck.length);
}
Change this:
for (i = 0; i < 1; i++) {
drawCard(playersHand);
}
to this:
for (var i = 0; i < 1; i++) {
drawCard(playersHand);
}
although why you need a loop here anyway is baffling.

JS crashes sometimes with Timer scramble

My Javascript timer is for people with a rubiks cube with generates a scramble (nevermind all this, but just to tell you I'm generating after each solve a new scramble will be generated) and my scrambles do actually have a while (true) statement. So that does crash my script, but it 95/100 times stops just before the script crashes but I don't wanna have any times.
Let me explain a bit more detailed about the problem.
Problem: javascript crashes because my script takes too long to generate a scramble.
Below you have 3 functions I use.
This function generates a scramble with the Fisher-Yates shuffle.
Timer.prototype.generateScramble = function(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
This function validates the input e.g. I receive an array as the following:
Here I only have to check the first character. That's why I use the seconds [ ] notation. I don't want people get an F with an F2 e.g.
var scr = ["F","R","U","B","L","D","F2","R2","U2","B2","L2","D2","F'","R'","U'","B'","L'","D'"]
Timer.prototype.validateScramble2 = function(array) {
var last = array.length-1;
for (var i = 0; i < array.length-1; i++) {
if (array[i][0] == array[i+1][0]) {
return false;
}
}
for (var i = 0; i < array.length-2; i++) {
if (array[i][0] == array[i+2][0]) {
return false;
}
}
if (array[0][0] == [last][0]) {
return false;
}
return true;
};
The above functions are just waiting to be called. Well in the function below I use them.
Timer.prototype.updateScramble2 = function(scrambleArr, len, type) {
var self = this;
var scramble = '', j, updatedArr = [];
while (updatedArr.length < len) {
j = (Math.floor(Math.random() * scrambleArr.length));
updatedArr.push(scrambleArr[j]);
}
while (!self.validateScramble2(updatedArr)) {
updatedArr = self.generateScramble(updatedArr);
}
for (var i = 0; i < updatedArr.length; i++) {
scramble += updatedArr[i] + ' ';
}
scrambleDiv.innerHTML = scramble;
};
I assume you guys understand it but let me explain it briefly.
The first while-loop adds a random value from the given array(scrambleArr) into a new array called updatedArr.
The next while-loop calls the validateScramble2() function if there isn't in an array F next to an F2.
The for-loop adds them into a new variable added with a whitespace and then later we show the scramble in the div: scrambleDiv.innerHTML = scramble;
What do I need know after all this information?
Well I wanna know why my updateScramble2() functions lets my browser crash every time and what I do wrong and how I should do it.
I'm not entirely sure I understand the question, but from the way your code looks, I think you have an infinite loop going on. It appears as if validateScramble2 always returns false which causes your second loop in updateScramble2 to perpetually run.
I suggest you insert a breakpoint in your code and inspect the values. You could also insert debugger; statements in your code, works the same way. Open dev tools prior to doing these.
A suggestion is instead of using loops, use a timer. This breaks up your loop into asynchronous iterations rather than synchronous. This allows the browser breathing space for other operations. Here's an example of a forEachAsync:
function forEachAsync(array, callback){
var i = 0;
var timer = setInterval(function(){
callback.call(null, array[i]);
if(++i >= array.length) clearInterval(timer);
}, 0);
}
forEachAsync([1,2,4], function(item){
console.log(item);
});
You can take this further and use Promises instead of callbacks.

Function is not completely executed

I have this function that causes the other functions to be skipped
I was just wondering what's wrong?
function sToLeftDiagonal(){
alert("sToLeftDiagonal");
var x, y;
var dCtr = 0;
var hLoop = varInit.maxRow;
for(var fifteen = 0; fifteen <= 3; fifteen++){
x = 0;
y = 5 - fifteen;
for(var xy = 0; xy <= hLoop ; xy++){
if (board[y][x] == player){
alert("plus");
dCtr++;
}else{
alert("negative");
dCtr = 0;
}
if (dCtr == varInit.cWins) {
dWinner(player);
}
x++;
y--;
}
hLoop--;
}
alert("end diagonal");
}
I've placed a lot of 'alert' to check whether they are executed or not, apparently
alert("end diagonal");
is not executed thus skips the next function in the main program
i know this is simple, i think i'm just overlooking some things..
thanks
i figured out what was causing the function to stop unexpectedly and not reach the last alert. it's because the values of [y] and [x] are wrong as i tried alerting every array index that the function goes through and variable y had an index of [-2] which wasn't suppose to be there.

Categories