re-Naming variables by properties (JavaScript) - javascript

In a JavaScript code, I am trying to re-name an object by its stored data. I tried using pathTo as suggested by this site (http://thedesignspace.net/MT2archives/000381.html), but my console returns "ReferenceError: 'pathTo' is undefined". My code looks something like this:
// This code defines the Object constructor Card, used to make the card objects
var Card = function() {
this.face = theFace(this);
this.suit = theSuit(this);
this.value = theValue(this);
};
// This code creates the Deck to be used.
var deck = [];
for ( i=0 ; i<52 ; i++ ) {
deck.push( i );
};
for ( i=51 ; i>0 ; i-- ) {
var random = Math.floor(Math.random()*i);
var temp = deck[random];
deck[random] = deck[i];
deck[i] = temp;
};
// 0-12 is Spades.
// 13-25 is Hearts.
// 26-38 is Clubs.
// 39-51 is Diamonds.
// Now we create the hand of the player and dealer
var player = [];
var dealer = [];
// Now to deal a card to player
player.push(deck.pop());
dealer.push(deck.pop());
// and another
player.push(deck.pop());
dealer.push(deck.pop());
// function theFace gives the face of a card
function theFace( card ) {
var faces = ["King","Ace","2","3","4","5","6","7","8","9","10","Queen","Jack"];
return(faces[card%13]);
};
// function theValue uses 'switch' to determine points from a card
function theValue(card) {
var value = card % 13;
switch( value ) {
case(0):
case(11):
case(12):
value = 10;
break;
case(1):
value = 11;
break;
default:
value = value;
break;
};
return value;
};
// function theSuit returns the suit of a card
function theSuit(card) {
var suit;
if(card>38) {
suit = "Diamonds";
}else if(card>25) {
suit = "Clubs";
}else if(card>12) {
suit = "Hearts";
}else {
suit = "Spades";
};
return suit;
};
// function toObject the first (numbered) card of of a hand
// and turns it into an Object with the desired properties
function toObject( hand ) {
var card = hand.shift();
if (typeof(card) !== "number") {
hand.unshift(card);
} else {
var card = new Card ();
card = pathTo[card.suit + card.face];
};
return hand;
};
console.log(player);
toObject(player);
toObject(player);
console.log(player);
I am trying to rename the card I am turning from a typeof==="number" to typeof==="object" so that when I run the code multiple times (hence the function) I do not have duplicate names of the objects in the array of hands.
Here are some examples of what my console is printing:
[ 19, 46 ]
ReferenceError: 'pathTo' is undefined
and
[ 31, 18 ]
ReferenceError: 'pathTo' is undefined
There MUST be a way to do this, I just cannot find how.
In function toObject I am trying to take the first number(card) in the hand array and turn it into an object describing its qualifiers as a card of the standard 52 card deck. EDIT: I just realized I'm not even pushing it back. I am going to try something to see if it will work.
EDITEDITEDIT_SOLVED:
I have done it! It turns out that I don't need to change the name, the code will keep it separate for me somehow. All I needed to do so that it runs correctly is this:
Replace
var Card = function() {
this.face = theFace(this);
this.suit = theSuit(this);
this.value = theValue(this);
};
with
var Card = function(card) {
this.face = theFace(card);
this.suit = theSuit(card);
this.value = theValue(card);
};
and
function toObject( hand ) {
var card = hand.shift();
if (typeof(card) !== "number") {
hand.unshift(card);
} else {
var card = new Card ();
card = pathTo[card.suit + card.face];
};
return hand;
};
with
function toObject( hand ) {
var card = hand.shift();
if (typeof(card) !== "number") {
hand.unshift(card);
} else {
var card = new Card (card);
hand.push(card);
};
return hand;
};
Thanks for the help!

As #mattbornski points out, there is no pathTo object in JavaScript and, as far as I know, it's not supported by any browser anywhere. That article seems to have omitted this part of their code.
Based on how you're trying to use it, though, you'll want to make a few changes to your code:
Create a pathTo object like this:
pathTo = {};
or
pathTo = new Object();
Then, give each new Card object a suit and face before you try to add it to pathTo (or before you try to use it to look up a card). For example, you could write:
myCard = new Card(23);
or
myCard = new Card('spade','2');
Finally, when your card has both a face and a suit, add it to the pathTo object like this:
pathTo[this.suit + this.face] = this; // use this inside the Card constructor
or
pathTo[myCard.suit + myCard.face] = myCard; // use this with an instance of a Card object
Then you can look up the cards with:
pathTo['spade2']

The website you are reading from is documenting array syntax. It is not documenting a function called pathTo - there is no such built in function, so referring to it will cause a ReferenceError.
Perhaps you should define an object and refer to that instead.

Related

Get payload from String

I have this String:
['TEST1-560', '{"data":[{"price":0.0815,"volume":0.2,"car":"BLUE"}],"isMasterFrame":false}']
I want to get the keys 'TEST1-560' which is always fist and "car" value.
Do you know how I can implement this?
This is a very, very scuffed code, but it should work for your purpose if you have a string and you want to go through it. This can definitely be shortened and optimized, but assuming you have the same structure it will be fine.:
// Your data
var z = `['TEST1-560', '{"data":[{"price":0.0815,"volume":0.2,"car":"BLUE"}],"isMasterFrame":false}']`;
var testName = z.substring(2).split("'")[0];
var dividedVar = z.split(",");
for (var ind in dividedVar) {
if (dividedVar[ind].split(":")[0] === '"car"') {
var car = dividedVar[ind].split(":")[1].split("}")[0].substring(1,dividedVar[ind].split(":")[1].split("}")[0].length-1);
console.log(car)
}
}
console.log(testName);
output:
BLUE
TEST1-560
In a real application, you don't need to log the results, you can simply use the variables testName,car. You can also put this in a function if you want to handle many data, e.g.:
function parseData(z) {
var testName = z.substring(2).split("'")[0];
var dividedVar = z.split(",");
for (var ind in dividedVar) {
if (dividedVar[ind].split(":")[0] === '"car"') {
var car = dividedVar[ind].split(":")[1].split("}")[0].substring(1, dividedVar[ind].split(":")[1].split("}")[0].length - 1);
}
}
return [testName, car]
}
This will return the variables values in an array you can use
const arr = ['TEST1-560', '{"data":[{"price":0.0815,"volume":0.2,"car":"BLUE"}],"isMasterFrame":false}']
const testValue = arr[0];
const carValue = JSON.parse(arr[1]).data[0].car;
console.log(testValue);
console.log('-----------');
console.log(carValue);
If your structure is always the same, your data can be extracted like above.

Issue with returning values from an object array

I'm pretty new (a few weeks in) to js and have a question about an incremental game I'm developing. My issue has to do with creating an array from an object I have and then fetching a property of the object, which is used in a compare statement and updated in my HTML.
I have the following object called UPGRADES:
var UPGRADES = {
newClothes: {
name: "New Clothes",
desc: "Give your bums a new look and some more motivation! \n Bum
production bonus: 100%",
moneyCost: 1000,
scienceCost: 10,
requiredScience: 10,
buildingAffected: BUILDINGS.bumBuilding,
upgVal: 2,
id: 'newClothes'
},
//{upgrade 2}
//{upgrade 3 etc.}
}
For one part of my code I need to go through each element of UPGRADES, return the nth object WITHIN "upgrades" (with newClothes as index 0), and then call (Nth index.scienceCost).
So far I've done the following:
var numBuildings = objectLength(BUILDINGS);
var numUpgrades = objectLength(UPGRADES);
function checkVisiblityOnUpgrades () {
var upgArray = [];
for (var a = 0; a < numUpgrades; a++) {
upgArray[a] = Object.keys(UPGRADES)[a].toString();
console.log(UPGRADES.upgArray[a]);
if (UPGRADES.upgArray[a].requiredScience <= resources.science) {
var idString = upgArray[a].id.toString();
getId(idString.concat("Button")).style.visibility = "visible";
getId(idString.concat("MoneyCostDisp")).innerHTML =
numFormat(upgArray[a].moneyCost);
getId(idString.concat("ScienceCostDisp")).innerHTML =
numFormat(upgArray[a].scienceCost);
}
}
}
I get this error along with it:
Uncaught TypeError: Cannot read property '0' of undefined
at checkVisiblityOnUpgrades (game.js:268)
at update (game.js:290)
268 is console.log(UPGRADES.upgArray[a]);
I was wondering how I would actually go about grabbing the values of the object I wanted. I'm creating an array in checkVisibilityOnUpgrades() so I can iterate through each upgrade with a for loop.
Another question I have is: If I was going to store 100+ instances of upgrades, would it be better to switch UPGRADES to an array rather than its own object? That way I could grab values a lot more easily.
You can drastically simplify your initial logic there with Object.entries:
Object.entries(UPGRADES).forEach(({ key, thisUpgradeObject }) => {
// `key` references the outer property, eg., 'newClothes'
// `thisUpgradeObject` references the inner object
});
So
Object.entries(upgArray).forEach(({ key, obj }) => {
const {
requiredScience,
id,
moneyCost,
scienceCost,
} = obj;
if (requiredScience < resources.science) return;
const idString = id.toString();
getId(idString.concat("Button")).style.visibility = "visible";
getId(idString.concat("MoneyCostDisp")).innerHTML = numFormat(moneyCost);
getId(idString.concat("ScienceCostDisp")).innerHTML = numFormat(scienceCost);
});
I see the problem here:
You create an array called upgArray, but then try to access UPGRADES.upgArray which is undefined. What you want to write there is likely UPGRADES[upgArray[a]].
function checkVisiblityOnUpgrades () {
var upgArray = Object.keys(UPGRADES);
for (var a = 0; a < numUpgrades; a++) {
if (UPGRADES[upgArray[a]].requiredScience <= resources.science) {
var idString = UPGRADES[upgArray[a]].id.toString();
getId(idString.concat("Button")).style.visibility = "visible";
getId(idString.concat("MoneyCostDisp")).innerHTML =
numFormat(UPGRADES[upgArray[a]].moneyCost);
getId(idString.concat("ScienceCostDisp")).innerHTML =
numFormat(UPGRADES[upgArray[a]].scienceCost);
}
}
}

Make Objects for every item in List

I have an array barcodeList that stores different barcode numbers. I want to make every single one of them into a different object with the key being the barcode numbers and having different properties. Then I want to put them all into one big object foodItems. How can I do this.
Also, I realized that numbers can't be used to make variables, so I would want to put a keyword in front of them. Also, the image and ingredient values of null are just placeholders for now.
Wanted Result -
foodItems = {
Data9001: {
image : null
ingredients : null
}
Data9002: {
image : null
ingredients : null
}
}
From barcodeList = [9001, 9002]
Any recommends methods to user or keywords would be appreciated as well.
Attempted:
barcodeList.push(code)
var Food = function() {
this.image = "noImage.png"
this.nutrients = null
this.ingredients = null
}
var foodItems = {}
for (var i in barcodeList) {
//Some append function
var something = new Food()
}
To use the bracket notation to create the keys
var barcodeList = [9001, 9002];
var foodItems = {};
barcodeList.forEach(function(item){
foodItems['Data'+item] = {
image : null,
ingredients : null
};
});
console.log(foodItems);
First of all, I didn't understand, what do you mean by this
I realized that numbers can't be used to make variables
but as per your requirement, you can do something like this
var barcodeList = [9001,9002];
var foodItems = {};
for (var i = 0; i < barcodeList.length; i++) {
foodItems[barcodeList[i]] = {
image : null,
ingredients : null
}
}
console.log(foodItems)
Edited:
As per your code you can do this
var barcodeList = [9001, 9002]
var foodItems = {};
var Food = function() {
this.image = "noImage.png"
this.nutrients = null
this.ingredients = null
}
var foodItems = {}
for (var i = 0; i < barcodeList.length; i++) {
var something = new Food()
foodItems[barcodeList[i]] = something;
}
console.log(foodItems);
Not sure, how far you have gone with your answer. I would use
the Array.prototype.map() to create an array of Data objects and then use the reduce to concatenate.
Few pointers
As you need keys to begin with Data I would use ['Data'+barcode] to create them.
I will also use the ES6 spread operator to concatenate.
Here is the working code.
"use strict"
var barcodeList = [9001, 9002];
var result = barcodeList.map(function(barcode){
return {
['Data'+barcode]: {
image: null,
ingredients : null
}
}
}).reduce(function(prevValue,currValue){
return {...prevValue, ...currValue};
});
console.log ( result);

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.

Define variables u=using for loop

I am new to javascript, how can I write this using for loop?
SortingPageAudio.prototype.cardAudios = function(cardNumber) {
var page = tabs.page;
var card1Audio = page.card1Audio;
var card2Audio = page.card2Audio;
var FRcard1Audio = card1Audio.replace("e_", "f_");
var FRcard2Audio = card2Audio.replace("e_", "f_");
if(cardNumber == '1')
{
playAudio.playFiles(FRcard1Audio));
}
else if(cardNumber == '2')
{
playAudio.playFiles(FRcard2Audio));
}
};
I don't see any need for a loop, as the function either does card 1 or card 2. If you want the code to be less repetitive, you can do this:
SortingPageAudio.prototype.cardAudios = function(cardNumber) {
var cardAudio = tabs.page["card" + cardNumber + "Audio"];
var FRcardAudio = cardAudio.replace("e_", "f_");
playAudio.playFiles(FRcardAudio);
};
In JavaScript, you can refer to a property either using dot notation and a property name literal (obj.foo), or using brackets notation and a property name string (obj["foo"]). In the latter case, the string can be the result of any expression.
If you wanted to call cardAudios for both cards, you could do it like this:
[1, 2].forEach(instance.cardAudios, instance);
(Where instance is a SortingPageAudio instance.)
Or with a simple for loop:
var card;
for (card = 1; card <= 2; ++card) {
instance.cardAudios(card);
}
Or of course:
instance.cardAudios(1);
instance.cardAudios(2);

Categories