I'm having issues with pushing object into an array.
I set an object with values and push them to the array. I then change some of the values of the object and push the object into the array again.
However, on inspection, both objects pushed into the array are identical, both object's values are identical to the last object that was pushed into the array.
let ProductPosition = function (x, y) {
this.x = x;
this.y = y;
}
let PalletType = (function () {
function PalletType() {
this.PatternType = '';
this.ProductWidth = 0;
this.PalletWidth = 0;
this.ProductPositions = [];
}
});
function getPalletPositions(pallet, pattern) {
pal.ProductPositions = [];
let posn = new ProductPosition();
switch (pattern) {
case '1U1':
posn = [];
posn.y = pal.PalletWidth / 2;
posn.angle = 0;
posn.apprDir = 0;
pallet.ProductPositions.push(posn);
break;
case '2U1':
posn = [];
posn.y = pal.PalletWidth / 2 + pal.ProductWidth / 2;
console.log('y pos 0 ' + posn.y);
pal.ProductPositions.push(posn);//first push
posn.y = pal.PalletWidth / 2 - pal.ProductWidth / 2;
console.log('y pos 1 ' + posn.y);
pallet.ProductPositions.push(posn);//first push
break;
}
}
let pal = new PalletType();
pal.PalletWidth = 1165;
pal.ProductWidth = 400
let pat = '2U1';
getPalletPositions(pal, pat);
pal.ProductPositions.forEach(function (pos) {
console.log("pos.y:" + pos.y);
});
Actual output:
y pos 0 782.5 <-value of y of first push
y pos 1 382.5 <-value of y of second push
pos.y:382.5 <-should be 782.5
pos.y:382.5
I'd expect:
y pos 0 782.5 <-value of y of first push
y pos 1 382.5 <-value of y of second push
pos.y:782.5
pos.y:382.5
I'm totally baffled and tried a few things, but to no avail.
You were mutating that object you can use spread operator or Object.assign
Check below
let ProductPosition = function (x, y) {
this.x = x;
this.y = y;
}
let PalletType = (function () {
function PalletType() {
this.PatternType = '';
this.ProductWidth = 0;
this.PalletWidth = 0;
this.ProductPositions = [];
}
});
function getPalletPositions(pallet, pattern) {
pal.ProductPositions = [];
let posn = new ProductPosition();
debugger;
switch (pattern) {
case '1U1':
posn = [];
posn.y = pal.PalletWidth / 2;
posn.angle = 0;
posn.apprDir = 0;
pallet.ProductPositions.push(posn);
break;
case '2U1':
posn = [];
posn.y = pal.PalletWidth / 2 + pal.ProductWidth / 2;
console.log('y pos 0 ' + posn.y);
pal.ProductPositions.push({...posn});//first push
posn.y = pal.PalletWidth / 2 - pal.ProductWidth / 2;
console.log('y pos 1 ' + posn.y);
pallet.ProductPositions.push({...posn});//first push
break;
}
}
let pal = new PalletType();
pal.PalletWidth = 1165;
pal.ProductWidth = 400
let pat = '2U1';
getPalletPositions(pal, pat);
pal.ProductPositions.forEach(function (pos) {
console.log("pos.y:" + pos.y);
});
That's because "posn" is an Object, so you are actually pushing a reference to this object rather than a primitive value.
You could, for example, copy the object:
pallet.ProductPositions.push({...posn});
The Spread operator will create a shallow copy.
If you need a deep copy use the following:
pallet.ProductPositions.push(JSON.Parse(JSON.Stringify(posn)));
Pay attention that the JSON method is not able to copy functions.
You're trying to push the same object 2 times in the same array. The first time with some value and next time, you're modifying the value in the same object and pushing in the array. So in total the same object reference is getting modified. As a result, the array has same object added 2 times.
Another way is, you can use slice operator on your array to create new instance of the array and then do the second push. OR create 2 different variables and then push it.
Thank you all for your prompt responses, it is very much appreciated.
Solved by using:
let x;
let y;
let angle;
let apprDir;
and assigning these directly. Then:
pallet.ProductPositions.push(new ProductPosition(x, y, angle, apprDir));
Works a treat and simplified the code.
Related
This is all the js code, when i console log the raw variable it returns the shuffled deck, I do not understand that, i am new to js and i've tried this. but i don't really know how it works, also, what's the difference between var and let if you guys dont mind me asking? thank you.
function drawDeck(){
var deck = []
var value = [2,3,4,5,6,7,8,9,10,10,10,10,11]
for(var i=0;i<4;i++){
for (var j=0;j<13;j++){
deck.push(value[j])
}
}
return deck
}
function shuffleDeck(deck){
var currentPos = deck.length, tempPos , randPos
while (currentPos != 0){
randPos = Math.floor(Math.random() * currentPos)
currentPos -= 1
tempPos = deck[currentPos]
deck[currentPos] = deck[randPos]
deck[randPos] = tempPos
}
return deck
}
function drawCard(deck){
var card = deck.shift()
return card
}
var raw = drawDeck()
var deck = shuffleDeck(raw)
var card = drawCard(deck)
console.log(raw)
The shuffle function operates on the input element itself. Since you input raw to the shuffle function it self will be modified and thus you get the shuffled deck when logging it. It doesn't matter if it gets returned or not.
If you wanna preserve the original array, clone the array to a new variable inside the shuffle function and do the shuffling on the clone and return that.
var raw = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
var shuffled;
function shuffleDeck(deck) {
var currentPos = deck.length,
tempPos, randPos
var tempDeck = Array.from(deck);
while (currentPos != 0) {
randPos = Math.floor(Math.random() * currentPos)
currentPos -= 1
tempPos = tempDeck[currentPos]
tempDeck[currentPos] = tempDeck[randPos]
tempDeck[randPos] = tempPos
}
return tempDeck
}
shuffled = shuffleDeck(raw);
alert('original: ' + raw);
alert('shuffled: ' + shuffled);
I am looking for a way to replace a variable in a function with its actual value. I am going to convert this function into a string and send via a HTTP request and thus need to convert the variables inside the function with their values.
let x = Math.random();
let funcString = function () {
let y = x + 10;
return y;
}.toString();
// Send funcString as a parameter
For eg. in the above code if I send funcString as it is, whoever receiving it will have no idea what is the value of x.
Since I am ultimately sending a string I would like to send
"function () {let y = 0.53 + 10; return y;}" (assuming
Math.random() produced 0.53 at runtime).
Is there any way to do this?
I am doing this in a nodejs project so a npm module would be fine by me too.
Well if you are returning this function as a string, just use String#replace() method to replace x occurrence with its value.
This is how you should use it:
funcString.replace('x', x)
Demo:
let x = Math.random();
let funcString = function () {
let y = x + 10;
return y;
}.toString();
console.log(funcString.replace('x', x));
Edit:
If your variable has many occurrences and can be part of other variables just use a regex with replace method.
funcString.replace(/\bx\b/g, x)
Demo:
let x = Math.random();
let funcString = function () {
let y = x + 10;
let fix ='true';
let z = x * 2;
return y;
}.toString();
console.log(funcString.replace(/\bx\b/g, x));
use replace with regex, g will search all x-es
let x = Math.random();
let funcString = function () {
let y = x + 10;
let a = x + 10;
let b = x + 10;
return y;
}.toString().replace(/x/g, x);
console.log(funcString);
I am calculating row and column of a given point by javascript function.
To achieve this I have to declare global variables
var global_row;
var global_col;
Here is function body
function calculate_city_row_col(cur_city_id)
{
var r = 565;
var c = 1;
var max_city_id = 159895;
do{
if((r%2) == 0) c++;
max_city_id -= r;
r--;
}
while(cur_city_id <= max_city_id)
//Saving Result in seperate row and column
global_row = r + 1; //Global Variable
global_col = c + (cur_city_id - (max_city_id + 1)); //Global Variable
}
Here is function call
var city_id = 1244;
calculate_city_row_col(city_id);
var city_row = global_row;
var city_col = global_col;
Is there anyway to directly pass local variables? (without using global variables)
like this
calculate_city_row_col(cur_city_id, city_row_ref, city_col_ref);
Just return an object:
function calculate_city_row_col(cur_city_id)
{
var r = 565;
var c = 1;
var max_city_id = 159895;
do{
if((r%2) == 0) c++;
max_city_id -= r;
r--;
}
while(cur_city_id <= max_city_id)
return {
row: r + 1,
col: c + (cur_city_id - (max_city_id + 1))
};
}
var rowAndCol = calculate_city_row_col(1244);
var city_row = rowAndCol.row;
var city_col = rowAndCol.col;
Can we pass variables by reference in JavaScript Function
No. JavaScript is purely pass-by-value (the value passed when you pass an object around is an object reference, but it's still a value).
Your options are:
Have the function return an object (or array)
function calculate_city_row_col(cur_city_id)
{
var r = 565;
var c = 1;
var max_city_id = 159895;
do{
if((r%2) == 0) c++;
max_city_id -= r;
r--;
}
while(cur_city_id <= max_city_id)
//Saving Result in seperate row and column
return {
row: r + 1,
col: c + (cur_city_id - (max_city_id + 1))
};
}
Usage:
var result = calculate_city_row_col(someCityId);
console.log(result.row);
console.log(result.col);
Have the function accept a reference to an object (or array) that it updates
function calculate_city_row_col(cur_city_id, result)
{
var r = 565;
var c = 1;
var max_city_id = 159895;
do{
if((r%2) == 0) c++;
max_city_id -= r;
r--;
}
while(cur_city_id <= max_city_id)
//Saving Result in seperate row and column
result.row = r + 1;
result.col = c + (cur_city_id - (max_city_id + 1));
}
Usage:
var result = {};
calculate_city_row_col(someCityId);
console.log(result.row);
console.log(result.col);
Barring a strong reason to go with #2 in a specific situation, #1 is usually the best option. For instance, if you were calling this function thousands of times in a tight loop, there might be a justification for reusing a single object (by passing it in) instead of creating a new object every time.
I am trying to simulate data to a function that would usually receive a JSON parsed data structure. When running this I get an error TypeError: can't convert undefined to object here: data.targets[i] = {
What am I doing wrong?
function SendFakeTargets(maxTargets, interval) {
var data = {};
data.timestamp = +new Date;
var time = data.timestamp * 0.0005;
var x = Math.sin(time) * 192 + 256;
var y = Math.cos(time * 0.9) * 192 + 256;
console.log(x, y);
for (var i = 0; i < maxTargets; i++) {
console.log(i);
data.targets[i] = { //error is here
id: i,
x: x + (i * 10),
y: y + (i * 10)
};
}
HandleTargetData(data);
setTimeout("SendFakeTargets("+maxTargets+", "+interval+")", interval);
}
you should previously declare
data.targets = [];
before using data.targets[i] inside the loop, otherwise data.targets is undefined. In a shorter way you could write
var data = {
timestamp : +new Date,
targets : []
};
And as a side note, never use strings in setTimeout/Interval. Do instead
setTimeout(function() {
SendFakeTargets(maxTargets, interval);
}, interval);
I think you need to initialize the targets array before using it, as it is undefined. You are defining data as
var data = {}
which is declaring it as an empty object, anything else that you're doing with it is added on the fly - arrays need to be initialized before you can call any index in them. I believe what you need to do is:
var data = { targets: [] }
You never declared "data.targets" as a an object so javascript doesn't know how to assign anything to it.
At the top of your code just define "targets":
data.timestamp = +new Date;
data.targets = {} or [];
...
I am currently working on making a multiplayer Snake game in HTML5 Canvas with Javascript.
The code below is function that handles the random placement of food for the snake. The problem with the piece of code is that it give me the x and y in while(map[x][y]); back as something he can not read even though it does generate a random number.
This is the exact error:
"Uncaught TypeError: Cannot read property '20' of undefined"
The '20' is the random generated number (and will be the grid position of the food in a two dimensional array) and changes every time I restart the program or refresh the webpage. Can someone explain what I need the change in order to define x and y and place my food?
function rand_food(){
var x, y;
do {
x = MR() * this.rect_w|0;
y = MR() * this.rect_h|0;
}
while (map[x][y]); <-- Here is the error
map[x][y] = 1;
this.ctx.strokeRect(x * 10+1, y * 10+1, 8, 8);
}
Here is another code snippet which defines the map.
this.map = [];
// Map positions
//*
for (i = 0; i < this.rect_w; i++){
map[i] = [];
}//*/
After trying Sean's suggestion my code now looks like this: But it still gives me same error. Any other suggestion?
function SnakeGame(){
this.map = [];
for (i = 0; i < this.rect_w; i++){
this.map[i] = [];
}
function rand_food(){
var x, y;
console.log("Map length: " + this.map.length);
do {
x = MR() * this.rect_w|0;
y = MR() * this.rect_h|0;
console.log("x: " + x);
console.log("y: " + y);
}
while (this.map[x][y]);
this.map[x][y] = 1;
this.ctx.strokeRect(x * 10+1, y * 10+1, 8, 8);
}
this.map and map are not the same thing.
If you are inside an object then this.map is a public variable of the object, and map is a local variable.
Try something like this:
this.map = [];
// Map positions
for (var i = 0; i < 10; i++){
this.map[i] = [];
}
and in the rand_food function also use this.map.
Here are two possible ways you can go:
//using public variable
function SnakeGame() {
this.map = [];
// Map positions
for (var i = 0; i < 10; i++){
this.map[i] = [];
}
function rand_food() {
// refer to this.map here
this.map[0];
}
};
// using local variable
function SnakeGame() {
var map = [];
// Map positions
for (var i = 0; i < 10; i++){
map[i] = [];
}
function rand_food() {
// refer to map here
map[0];
}
};
If map was not defined you would normally get a ReferenceError, so map is defined but probably:
not assigned to anything
defined/assigned after beeing used
hoisted by beeing defined in a condition that do not execute
example
if (0) {
var foo = 1;
}
console.log(foo) //= undefined
console.log(foo[20]) // TypeError…
console.log(bar) // ReferenceError…