Javascript internally changing array values, any fix? - javascript

I'm making a chess game. And I'm storing some tiles of the chessboard for some usage in my program in an array. The problem is, when I update the values in the array, and log them onto the console, I can see the values of the array, which are correct. But, upon clicking and checking the actual values in the console, the array shows different values.
I'm using google chrome's console.
I've already seen another stack overflow saying that this is a known "bug", but the developers won't fix it because it's not actually a bug.
Here's what I see in the console:
(2) ["a6", "a5"]
0: "`6"
1: "b6"
length: 2
__proto__: Array(0)
As you see, the values in the array I see are different than the values that are stored in the array. And this causes many other problems in my program which rely on the contents of this array.
What I want to know is if this is common, and also if there is any fix. Or maybe some scenarios where cases like this occur.
Also, I'm still unsure, for the array shown above ^, are the actual values of the array the values I see ("a6" and "a5"), or the wrong values shown internally ("`6" and "b6").
Please help, if this doesn't work, it will be extremely difficult to finish the project I'm working on.
Here is the code I use to update the array:
let moves = [];
if (tile.slice(1, 2) == 7 && b1.board[dd].piece == null && b1.board[d].piece == null) {
moves.push(d);
moves.push(dd);
}
if (tile.slice(1, 2) == 7 && b1.board[d].piece == null && b1.board[dd].piece != null) {
moves.push(d);
}
if (parseInt(tile.slice(1, 2)) > 1 && tile.slice(1, 2) != 7 && b1.board[d].piece == null) {
moves.push(d);
}
if (tile.charCodeAt(0) > 97 && parseInt(tile.slice(1, 2)) > 1 && b1.board[ld].piece != null && b1.board[ld].piece.slice(0, 1) == "w") {
moves.push(ld);
}
if (tile.charCodeAt(0) < 104 && parseInt(tile.slice(1, 2)) > 1 && b1.board[rd].piece != null && b1.board[rd].piece.slice(0, 1) == "w") {
moves.push(rd);
}
console.log(moves);
just to provide some context, I make an array called moves. I push values into the array based on some conditions. Then I log the array onto the console, which is what I showed above.
The if statements are working because the values I see in the array are correct. But as you know, upon clicking and checking the internal values in the console, they are wrong.
The result I am expecting from the console is:
(2) ["a6", "a5"]
0: "a6"
1: "a5"
length: 2
__proto__: Array(0)
How do I fix this problem?

Not sure this is the cause, but when console.log, Chrome and other browser don't output the serialized values of the arrays/objects but just stores the reference on them. Later when you inspect these arrays/objects Chrome will show the current values in those arrays, not the values that were present at the time of logging.
Try logging with console.log(JSON.stringify(thingToLog)). Or even better with console.log(JSON.stringify(thingToLog, undefined, ' ')).

Related

Multiple selection in single Dropdown

I found this code on reddit that works quite well. Anyway, when I try to delete the information that I completed with the dropdown, or modify something, an undefined value shows up and I can not delete it. How could I do that?
Code:
function onEdit(e){
if(e.range.columnStart != 6 || e.oldValue == undefined) return;
e.range.setValue(e.oldValue+" | "+e.value);
}
Besides, when more than 1 option is added on my cell, an 'invalid' message shows up. How could I delete it? It's a default config from the Data Validation.
So far your code snippet works on mine properly. (I can't seem to replicate your issue)
But for you, it isn't (that I am not sure). Try to include the condition where e.value is null (that happens when you delete the cell value). Your code should look like this.
Code:
function onEdit(e){
if(e.range.columnStart != 6 || e.oldValue == null || e.value == null) return;
e.range.setValue(e.oldValue+" | "+e.value);
}
Note:
Try to log the values before comparing them in a condition. It's true that in a == sense, null and undefined are the same as both of them return FALSE, but they have different types. If you have used ===, then they are not equal.
If the cell is deleted (as you can see on the image below), both oldValue and value becomes null.
Cloud logs (blank -> yes -> no -> delete cell):

Logging objects shows all properties but logging the properties individually shows 'undefined'

I'm trying to port a PHP function I built to Javascript and have been finding many differences that cause a lot of extra work. I am stuck on this one and cannot find any logic to it:
X: 95.29
Y: 27.39
testParse2.RXdec : 0.1
var curPos={};
curPos={};
console.log(curPos); //X:97.19 Y:27.39 (I expect an empty object)
console.log(curPos['X']); //undefined (seems ok but makes no sense with above)
console.log(curPos['Y']); //undefined (seems ok but makes no sense with above)
for(var Ri=0; Ri < 20; Ri++){
curPos['X'] = "";
curPos['Y'] = "";
console.log(curPos['X']); // "" (seems ok)
console.log(curPos['Y']); // "" (seems ok)
console.log(curPos); //X:97.19 Y:27.39
curPos.X = (((XY(lastPos[AV['A']], 'X')*1)+(testParse2.RXdec*1*Ri)).toFixed(10)*1);
curPos.Y = (((XY(lastPos[AV['B']], 'Y')*1)+(testParse2.RYdec*1*Ri)).toFixed(10)*1);
console.log(curPos); // X:97.19 Y:27.39 (I expect X:95.29 + 0.1 each loop Y:27.39)
console.log(curPos.X); // 95.29 (correct by why is above different?)
console.log(curPos.Y); // 27.39 (correct by why is above different?)
}
The things that confuse me the most are:
curPos gets a value before the loop even starts. The value is the
value that curPos should have after the final iteration.
during the loop the console log for curPos and curPos.X or .Y do not
contain the same values.
during the loop the console log for curPos is always the same despite changing .X and .Y each iteration
Edit: #str gave the correct explanation for the console trouble but it seems that this problem is beyond the console and actually effects the object values.
after using JSON.strigify I can see this (which is good):
console.log(JSON.stringify(testParse2));
"Xdec":97.99
"Xdec":98.09
"Xdec":98.19
but now I try to transfer the data to its final array but that final array is filled with 'lazy' values:
T['tool'][T['curTool']]['points'][lineID] = testParse2;
console.log(JSON.stringify(T));
"Xdec":98.19,"Ydec":27.39,"curX":323.19,"curY":177.39
"Xdec":98.19,"Ydec":27.39,"curX":323.19,"curY":177.39
"Xdec":98.19,"Ydec":27.39,"curX":323.19,"curY":177.39
If I stop using objects in the loop and switch to variables then build my final array like this it works:
T['tool'][T['curTool']]['points'][lineID] = {'curX' : curX,
'curY' : curY,
'TYP' : 'DR',
'lineID' : lineID,
'lineName' : lineName,};
How do you send the actual object values at a particular iteration of a loop to a different array?
Browsers evaluate objects lazily in when logging. So when you expand them after the loop, they will show the properties they have at the moment of expanding and not the ones they had when the object was logged.
You can verify that by using
console.log(JSON.stringify(curPos));
instead of
console.log(curPos);

Array has only 4 elements but it shows like it has 5 elements even after removing empty elements

I have an array with 4 elements and in one scenario I want to pop one element from the array. But after pop array gives the same result as before.
I have checked in the console window and there I have find a different behavior like array length is 4 and it shows like it has 5 elements.
I have tried to remove the empty elements also but still the same issue is coming .
var brudcrumbDataArray=JSON.parse(brudcrumbDataString);
brudcrumbDataArray = brudcrumbDataArray.filter(function(n){ return n != undefined });
console.log(brudcrumbDataArray)
brudcrumbDataArray.pop();
console.log(brudcrumbDataArray)
Her is the array :
[{"name":"Dashboard","url":"","path":"","class":"icon-home2 position-left","type":"MainMenu","queryParams":""},{"name":"Main","url":"#/dashboard","path":"/dashboard","class":"","type":"SubMenu","queryParams":""},{"name":"Sub Accounts","url":"#/account/customers","path":"/account/customers","class":"","type":"SubMenu","queryParams":""},{"name":"End Users","url":"#/account/endusers","path":"/account/endusers","class":"","type":"SubMenu","queryParams":""},{"name":"Profile","url":"#/user-dashboard","path":"/user-dashboard","class":"","type":"SubMenu","queryParams":""}]
After pop also array gives the same data and same length. Can someone help me to solve this issue ?
Snippet, check your console to see the problem:
var brudcrumbDataString =`[{"name":"Dashboard","url":"","path":"","class":"icon-home2 position-left","type":"MainMenu","queryParams":""},{"name":"Main","url":"#/dashboard","path":"/dashboard","class":"","type":"SubMenu","queryParams":""},{"name":"Sub Accounts","url":"#/account/customers","path":"/account/customers","class":"","type":"SubMenu","queryParams":""},{"name":"End Users","url":"#/account/endusers","path":"/account/endusers","class":"","type":"SubMenu","queryParams":""},{"name":"Profile","url":"#/user-dashboard","path":"/user-dashboard","class":"","type":"SubMenu","queryParams":""}]`;
var brudcrumbDataArray=JSON.parse(brudcrumbDataString);
brudcrumbDataArray = brudcrumbDataArray.filter(function(n){ return n != undefined });
console.log(brudcrumbDataArray)
brudcrumbDataArray.pop();
console.log(brudcrumbDataArray)
A result on the console seems to be correct. Both the logs on the console window are showing the result after the operation. Why is the first log showing a result in it? because, in javascript, complex objects get stored by reference, that's why your first log does show a result in it too.
Store by reference? what does it mean? : https://docstore.mik.ua/orelly/webprog/jscript/ch04_04.htm
Try below one,
var brudcrumbDataString =`[{"name":"Dashboard","url":"","path":"","class":"icon-home2 position-left","type":"MainMenu","queryParams":""},{"name":"Main","url":"#/dashboard","path":"/dashboard","class":"","type":"SubMenu","queryParams":""},{"name":"Sub Accounts","url":"#/account/customers","path":"/account/customers","class":"","type":"SubMenu","queryParams":""},{"name":"End Users","url":"#/account/endusers","path":"/account/endusers","class":"","type":"SubMenu","queryParams":""},{"name":"Profile","url":"#/user-dashboard","path":"/user-dashboard","class":"","type":"SubMenu","queryParams":""}]`;
var brudcrumbDataArray=JSON.parse(brudcrumbDataString);
brudcrumbDataArray = brudcrumbDataArray.filter(function(n){ return n != undefined });
console.log(JSON.parse(JSON.stringify(brudcrumbDataArray)))
brudcrumbDataArray.pop();
console.log(JSON.parse(JSON.stringify(brudcrumbDataArray)))
Look closely here, we are doing deep data copy with using JSON operations, by surrounding object in JSON.parse(JSON.stringify( )) and it won't point to reference anymore now.
And log will be more clear as below,
it showing because the reference to the same object so when you pop last element the object get modified and shows the length as 4 so the first consoled object also get updated.
var brudcrumbDataArray = [{"name":"Dashboard","url":"","path":"","class":"icon-home2 position-left","type":"MainMenu","queryParams":""},{"name":"Main","url":"#/dashboard","path":"/dashboard","class":"","type":"SubMenu","queryParams":""},{"name":"Sub Accounts","url":"#/account/customers","path":"/account/customers","class":"","type":"SubMenu","queryParams":""},{"name":"End Users","url":"#/account/endusers","path":"/account/endusers","class":"","type":"SubMenu","queryParams":""},{"name":"Profile","url":"#/user-dashboard","path":"/user-dashboard","class":"","type":"SubMenu","queryParams":""}]
//var brudcrumbDataArray=JSON.parse(brudcrumbDataString);
var newBrudcrumbDataArray = brudcrumbDataArray.filter(function(n){ return n != undefined });
console.log(brudcrumbDataArray)
newBrudcrumbDataArray.pop();
console.log(newBrudcrumbDataArray)

Finding neighbors in a game of five-in-a-row

I can declare a winner if a player gets five of their tokens in a row, and now I am trying to implement the feature of capturing an opponent's pieces. For example, I am player X, I can trap O's pieces like this X00X in any direction on the board. In order to implement this, is the following logic correct:
Find all neighbors around O, check and see if the neighbor is an X or an O, if there are two 0's in a row surrounded by an X on each side, I can take those pieces. Is there a better way to approach this problem? I am thinking of something like this:
function isOCaptured(token, row, col){
if(gameBoard[row][col]==="O" && gameBoard[row][col+1] === "X"
&& gameBoard[row][col-1] === "X"){
return true;
}
return false;
}
But it does not seems to return true when I place one O in between two X's.
Here is what my server.js and app.js look like right now: https://jsfiddle.net/Amidi/s3gnx3rL/4/ The HTML is just a 13 x 13 grid of buttons with an event attached to each which sends the buttons coordinates to the add() function in my app.js
Now, the problem seems to be that the code only works if the "O" was placed last. This can be solved with a for-loop.
for(var i = -1; i <= 1; i++) {
if (gameBoard[row][col+i]==="O" && gameBoard[row][col+i+1] === "X"
&& gameBoard[row][col+i-1] === "X") {
return true;
}
}
return false;
You can also use a slice:
// The closest 5 cells to the left/right of the newly added piece, as a string
var str = gameBoard[row].slice(col-2,col+3).join("");
// Look for the pattern "XOX" in those 5 cells. Double negation to return bool.
return !!str.match("XOX");
Old answer
According to your comment, the code was called like this:
if(isOCaptured(x,y)===true){console.log("y is between 2 x\s");
This means that the function is called with two instead of three arguments. That will result in the following values of the arguments: token = x, row = y and col = undefined.
The expression being evaluated will thus be:
gameBoard[y][undefined]==="O" && gameBoard[y][undefined+1] === "X"
&& gameBoard[y][undefined-1] === "X"
Which would evaluate as follows:
Evaluating gameBoard[y] will succeed, resulting in a column (the wrong one though).
Then we try indexing the column with undefined, and since the array doesn't contain an element called undefined, it will fail, resulting in (again) undefined.
Then we compare this value undefined with "0", which is obviously false.
The expression false && ... will return false, as will the whole function.
If the second part would have been executed, it would calculate undefined+1, which is (quite accurately) evaluated to NaN (not a number). The array doesn't contain NaN either, so this calculation would evaluated to false as well.
Now, for some advice:
The statement if(expr){return true} else {return false} can be simplified to just return expr.
These kinds of bugs are pretty easy to find if you use the Chrome Debugger (or Firebug for firefox), where you can step through the code and see exactly what happens and where stuff goes wrong.

Javascript lazy typecasting safety check

I am peer reviewing code written in vanilla javascript, and one of the authors occasionally performs a lazy-typecast if statement because he is evaluating values from a REST service that has very sloppy data. Occasionally a value representing money in USD comes back as a string, and sometimes as a number, probably depending on what validation was in place at the time the user entered the data over the years.
So sometimes we get a value of 150 and sometimes we get "150" (without the quotes, if you know what I mean).
The data is just displayed, and there are no math operations done against it: it simply needs to be compared to another number so some display styling can be done.
Instead of writing some function that checks the type of data and forces it to be a uniform type, the developer does something like this:
var baseVal = ReturnsAnIntegerValue(); // returns a number
var retrievedVal = CallToAwfulDataService(); // could return number or string
if (retrievedVal && retrievedVal == baseVal) {
// do stuff
}
else { ...
At first the == made me see a red flag, but when I asked him about it, he said that the initial check for if (retrievedVal && ... would prevent unexpected outcomes from situations where baseVal and retrievedVal are each some combination of null, 0, empty string, or undefined, like this:
if (null && null == undefined) // false | if (null == undefined) // true
if (0 && 0 == "") // false | if (0 == "") // true
if (0 && 0 == "0") // false | if (0 == "0") // true
if (0 && 0 == "") // false | if (0 == "") // true
You get the idea. I feel like this should be bad code because I was taught that the == is bad form, but the code is readable and concise, without the need for an extra function that type-converts just for show. I can't think of a scenario where we are likely to be hurt by it.
Is this bad code? Specifically: what is wrong with it? Is there a better practice for handling this?
edit
I forgot to mention, I have looked at a bunch of SO questions that mostly seem to back up the == is code smell school of thought, but I can't see what is technically risky about this scenario.
You should probably have some "normalize" function, and test cases with data samples from the backend.
Good practices generally assume that "all is fine" with the environment, which isn't your case.
Which ever way you go, you're doomed as far as "good practices" are concerned.

Categories