Using Array.splice removes strings from two arrays - javascript

So this is what I am dealing with:
At the top of the js file i declare these variables:
let teensArray = [];
let copyteensArray = [];
let teensArrayLength = 0;
let teensArrayPlayed = 0;
$.getJSON("json/teens.json", function(data) {
teensArray = data.statements;
copyteensArray = data.statements;
teensArrayLength = data.statements.length;
$(".teens .total-cards").text(teensArrayLength + " CARDS")
});
Everytime the mode is "teens" this executes:
if (mode == "teens") {
let currStatement = copyteensArray[getRandomInt(copyteensArray.length)]
let index = copyteensArray.indexOf(currStatement)
copyteensArray.splice(index, 1);
currentPack = "TEENS PACK";
currentColor = "#23B574";
srcImg = "svg/007-party hat.svg"
playedCardsText = ++teensArrayPlayed + " / " + teensArrayLength;
console.log(copyteensArray.length);
console.log(teensArray.length);
return currStatement;
}
The problem: The teensArray has the same values as copyteensArray after the if statement.
Example values:
Before if statement
teensArray["1","2","3","4"]
copyteensArray["1","2","3","4"]
Inside if statement
copyteensArray.splice(index, 1);
After the return inside the if statement
teensArray["1","3","4"]
copyteensArray["1","3","4"]
This function executes ONLY if the user decides to go back to another screen:
function reset() {
copyteensArray = teensArray;
teensArrayPlayed = 0;
}
Am I missing something?

copyteensArray = teensArray; makes the same pointer point to both of them. Consider using copyteensArray = [...teensArray]; which assigns brand new instance of teensArray content to copyteensArray

You have a "shallow" copy of the array, ie both the array point to the same objects. Any changes made to the shallow copy will change the original object.
You can visualize it as a shortcut in Windows. Whatever change you make to the shortcut also changes the original object.
Solve this making a hard copy. There are multiple ways in ES6 to do that.
hardCopy = [...OriginalArray];
And another way is to JSON.stringify() the object and parse it back.
hardCopy = JSON.parse(JSON.stringify(OriginalArray));
For your code, fix this by changing these lines
$.getJSON("json/teens.json", function(data) {
teensArray = [...data.statements];
copyteensArray = [...data.statements];

Related

Object being called with wrong properties

I am currently building a website like PCPartPicker but for watercooling parts for a school project. I dove in and I am having some issues. The most important on being this:
Here is my object constructor to start
var cpuCollection = [];
var myComputer = [];
function CPU(frequency,cores,socket,name) {
this.name = name;
this.frequency = frequency;
this.cores = cores;
this.socket = socket;
cpuCollection.push(this);
}
var i75930k = new CPU(3.6, 6, 2011.3, "i7 5930k");
var i54690k = new CPU(3.6, 4, 1150, "i5 4960k");`
After I built the object constructor I made some test objects using real computer parts.
In my HTML I have drop down menus that are populated by the objects on load using this code:
$(cpuCollection).each(function() {
$('#cpusel').append($("<option> " + this.name + "</option>"))
});
From there I wanted to make it so that when an option was selected in the dropdown the proper object would be pushed into the myCPU var for compatibility testing in another function. The code I used to accomplish this is as follows:
$('#cpusel').change(function() {
myCPU = new CPU();
$(cpuCollection).each(function(){
if(this.name = $('#cpusel :selected').text()) {
myCPU = this;
}
});
});
Unfortunately this code currently isn't working and is telling me that myCPU.socket is 1150 when the i75930k is selected when it really should be 2011.3. I am getting to wits end here and want to make some progress.
Thanks for the help in advance.
Edit: I fixed the equals sign issue and now I am thinking that the problem may be stemming from the way I push the objects into the cpuCollection array. When I try and log cpuCollection I get [CPU, CPU] which is obviously not what I want. How can I push the CPU objects on creation into cpuCollection with all of their properties intact.
Try this in your if() statement:
$('#cpusel').change(function() {
myCPU = new CPU();
$(cpuCollection).each(function(){
if(this.name === $('#cpusel :selected').text()) {
myCPU = this;
}
});
So, there were a few issues with some of your logic/syntax, and I will try to address them individually so you can better understand how I got a working solution:
1) You are pushing the element to an array from inside your object definition. This is typically bad practice, as it is not reusable, and will throw an error if an array called cpuCollection is not defined prior to the instantiation of that instance of the CPU object. It is better to say cpuCollection.push(new CPU(...));
2) When you append the options to the dropdown list, you should add the value property as well, so you can more easily grab the value in #3
3) If you set the value propery on the <option> elements, there is no need to look for the text of the selected option, you can simplify your selector to $('#cpusel').val()
4) There is no need to wrap your arrays in a jQuery object by saying $(cpuCollection).each(...), you can (and should) use the built-in vanilla javascript array operations.
5) I changed your .each() in the change handler to be a .some() this is because when you return true from .some() it stops any further iteration, which is what you want. Previously, it would continue to loop to the end, even if it already found the matching CPU.
6) I added a myCPU variable and instantiated it to null, so if you are running in strict mode, your change handler wouldn't throw an error for the variable not having been previously defined.
7) Your logic in your if statement was doing an assignment, rather than a comparison because you used = instead of == or ===, simple mistake.
Hope this helps!
var cpuCollection = [];
var myComputer = [];
var myCPU = null;
function CPU(frequency,cores,socket,name) {
this.name = name;
this.frequency = frequency;
this.cores = cores;
this.socket = socket;
}
cpuCollection.push(new CPU(3.6, 6, 2011.3, "i7 5930k"));
cpuCollection.push(new CPU(3.6, 4, 1150, "i5 4960k"));
cpuCollection.forEach(function(cpu, index) {
$('#cpusel').append($('<option value="'+ cpu.name + '">' + cpu.name + '</option>'))
});
$('#cpusel').change(function() {
myCPU = new CPU();
cpuCollection.some(function(cpu, index){
if(cpu.name === $('#cpusel').val()) {
myCPU = cpu;
return true;
}
});
console.log(myCPU);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="cpusel"></select>
There is simple way(s) :
var cpuCollection = [];
var myComputer = [];
function CPU(frequency,cores,socket,name) {
cpuCollection.push({
name: name,
frequency: frequency,
cores: cores,
socket: socket
});
}
var i75930k = CPU(3.6, 6, 2011.3, "i7 5930k");
var i54690k = CPU(3.6, 4, 1150, "i5 4960k");
$(cpuCollection).each(function(i,cpu) {
var option = $('<option/>').html(cpu.name).data('cpu',cpu);
$('#cpusel').append(option);
});
$('#cpusel').change(function() {
var selected = $(this).find('option:selected');
var text = $(selected).text();
var myCPU;
// You can simply use : myCPU = $(selected).data("cpu")
console.log('via data:',$(selected).data("cpu"));
$(cpuCollection).each(function(i,cpu){
if($.trim(cpu.name) == $.trim(text)) {
myCPU = cpu;
// return false; ==> break the each();
}
});
console.log('via each:',myCPU);
});
See this demo.

making JSON from string

I have a job to refractor strings to start using json so they can just pass json objects. So I have made array of names and then I'm trying to go through and make key and values but I'm getting an error in the console that it cant find x of no value. Can someone point me in the right direction?
var newName = ['ManagingOrg', 'ActiveOrg', 'Severity', 'SeverityClassification', 'WorkQueue', 'TicketState',................ to long to post];
$().each(newName, function (key, value) {
key = newName[this];
value = newValues[this] = $('#' + key).val();
newArray = [key][value];
newArray = JSON.stringify(newArray);
alert(newArray);
$('.results').html(origArray[TicketNumber]);
});
I'm assuming you have "newValues" and "origArray" defined elsewhere?
In any case you'll need to at least adjust the following:
"$().each" should be $.each
"newArray" should be defined outside and you should use newArray[key] = value
you don't have a variable "TicketNumber" defined and so you should wrap "TicketNumber" in quotes
this is a reserved word so you shouldn't use it in "newName[this]" or "newValues[this]"
I suggest using a for loop instead of $.each() based on what you're trying to do inside.
https://msdn.microsoft.com/en-us/library/bb299886.aspx
var origArray = [];
var newName = ['ManagingOrg', 'ActiveOrg', 'Severity', 'SeverityClassification'
];
for (var i = 0; i < newName.length - 1; i++) {
var object = {};
object[newName[i]] = newName[i];
object = JSON.stringify(object);
origArray.push(object);
}

create objects for loop and pushing them into an array js

I wish to create an array called allEnemies, which contains "bugs" which belong to a Class "Enemy". I'm trying to do it in a for loop because later on the var "bug" will be modified. The problem is that the objects created "if I'm creating them" don't get into the array "allEnmies". Thank you in advance.
var allEnemies = [];
var random_speed = function() {
return Math.floor(Math.random() * (300 - 80)) + 80;
};
var random_y = function() {
var postions = [60, 143, 226];
return positions[Math.floor(Math.random() * 3)];
};
var create_enemies = function() {
var bugs = 4;
for (var i = 0; i < bugs; i++) {
var bug = new Enemy();
bug.speed = random_speed();
bug.y = random_y();
bug.x = 0;
allEnemies.push(bug);
}
};
Demo - http://jsfiddle.net/ubkusb6r/
Ok, so a few things:
1) Since you've declared the for loop using an anonymous function assigned to a variable you need to invoke the function via that variable create_enemies(). Without this, your code won't run.
2) You need to create an Ememy constructor (if you haven't done so yet).
3) You misspell positions at one place in your code...leading to an error.
Take a look at the JSFiddle and let me know if it answers your question (the fiddle includes console.log statements to track the array).

How do I overwrite object properties in an array?

I would like to overwrite a certain allOrders[i] with data, similar to how I create a new one. For some reason I can't figure out what to search on.
I have an array of objects allOrders.
I have an object BusinessCard. I take the form fields, serialize() them, clean up the data with a regex, then push the them into an array.
allOrders.push(new BusinessCard(currentOrder.quantity, currentOrder.FullName, currentOrder.Title, currentOrder.CellNumber, currentOrder.OfficeNumber, currentOrder.FaxNumber, currentOrder.EmailAddress, currentOrder.Address, currentOrder.website, currentOrder.price));
I've tried searching for overwriting existing object properties in an array and the likes and haven't figured out what to do here.
My best guess was allOrders[i].push -- but it seems to me that I have to write a new function to replace each property in the object.
Right now I am using(because using serialize() on the form inputs doesn't help me at all:
allOrders[i].quantity = $('#bcQuantity').val();
allOrders[i].fullname = $('#fullName').val();
allOrders[i].title = $('#Title').val();
allOrders[i].cell = $('#CellNumber').val();
allOrders[i].office = $('#OfficeNumber').val();
allOrders[i].fax = $('#FaxNumber').val();
allOrders[i].email = $('#EmailAddress').val();
allOrders[i].address = $('#Address').val();
allOrders[i].website = $('#website').val();
allOrders[i].price = $('#bcCostBeforeCart').text();
There has to be a smarter way to do this. Thank you.
EDIT:
function getFormData(formId) {
var currentForm = '#' + formId;
var currentPrice = $('#bcCostBeforeCart').text();
var currentFormData = $(currentForm).serialize();
var currentFormDataFinal = currentFormData + '&price=' + currentPrice;
return JSON.parse('{"' + decodeURI(currentFormDataFinal.replace(/\+/g, " ").replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}');
}
MEANING i could be using
currentOrder = getFormData('businessCardForm');
then
allOrders[i] = currentOrder;
Seems odd that you would be updating all items with the selector's you're using, but I would wrap up getting the updated order information then, you can run thru a loop.
Depending on your output, as long as it's outputing the respective properties and values of an order object you could just do:
for(int i =0; i < allOrders.length; i++){
var currentFormId = '' // update this for each iteration.
allOrders[i] = getFormData(currentFormId);
}
allOrders[i] = getUpdatedOrder();
function getUpdatedOrder() {
var order = {};
order.quantity = $('#bcQuantity').val();
order.fullname = $('#fullName').val();
order.title = $('#Title').val();
order.cell = $('#CellNumber').val();
order.office = $('#OfficeNumber').val();
order.fax = $('#FaxNumber').val();
order.email = $('#EmailAddress').val();
order.address = $('#Address').val();
order.website = $('#website').val();
order.price = $('#bcCostBeforeCart').text();
return order;
}

Why is my for loop stopping after one iteration?

Racking my brains on this one. I have the code below: the first stages of a JavaScript game. All the objects are well-defined and I'm using jQuery for DOM interaction. The puzzle is created with the following JS code:
var mypuzzle = new puzzle("{solution:'5+6+89',equations:[['5+3=8',23,23],['5+1=6',150,23],['5+3=6',230,23]]}");
However, the loop at the bottom of the code won't go further than the first iteration. Any idea why? No errors are thrown at all.
function equationBox(equation, top, left) {//draggable equation box
this.reposition = function() {
this.top = 0;
this.left = 0;
}
this.top = 0;//make random
this.left = 0;//make random
this.equation = equation;
if(top && left) {
this.top = top;
this.left = left;
}
this.content = this.equation.LHS.string + '<span> = </span>' + this.equation.RHS.string;
this.DOM = $('<li>').html(this.content);
}
function puzzle(json) {
this.addEquationBox = function(equationBox) {
$('#puzzle #equations').append(equationBox.DOM);
}
this.init = function() {
//this.drawPuzzleBox();
this.json = JSON.parse(json);
this.solution = new expression(this.json.solution || '');
this.equations = this.json.equations || [];
var iterations = this.equations.length;
for(i=0;i<iterations;i++)
{
console.log(i);
this.addEquationBox(new equationBox(stringToEquation(this.equations[i][0]),this.equations[i][1], this.equations[i][2]));
}
}
this.init();
}
Possibly your failure to scope your counter variable is doing it, especially if you make a habit of it (since you're using the global variable of that name, and any loops you wrote in any code you're calling may be doing the same thing). Try:
for(var i=0;i<iterations;i++)
because this.equations = this.json.equations || [] , and, since this.json.equations is undefined, it get assigned to []
Assuming you're using JSON.parse as defined at https://github.com/douglascrockford/JSON-js/blob/master/json2.js, it appears that your json string is not parsing properly:
var string1 = "{solution:'5+6+89',equations:[['5+3=8',23,23],['5+1=6',150,23],['5+3=6',230,23]]}"
JSON.parse(string1); // throws SyntaxError("JSON.parse")
When I use JSON.stringify, defined in the same file, to create a JSON string from your object:
var obj = {solution:'5+6+89',equations:[['5+3=8',23,23],['5+1=6',150,23],['5+3=6',230,23]]}
var string2 = JSON.stringify(obj);
// {"solution":"5+6+89","equations":[["5+3=8",23,23],["5+1=6",150,23],["5+3=6",230,23]]}
JSON.parse(string2); // returns a proper object
Note that the string that JSON.stringify is creating is different than the one you are trying to use, which might be the cause of your problem.

Categories