Cannot read undefined property error - building object properties in JavaScript - javascript

I am taking an online JavaScript class and am stuck on a problem involving objects. In the following code, my assignment is to output a string that retrieves the name of each ranger (e.g. lighthouseRock.ranger1.name) and match their station to the corresponding item in the superBlinders array.
If I hard-code the ranger1 property, the output format is in the right ballpark. However, if I try to be creative and build a variable (thisRanger) to dynamically insert the appropriate ranger into my object, the routine returns an error "TypeError: Cannot read property 'name' of undefined". My thisRanger variable builds OK but whenever I try to insert it into my chain after lightHouseRock it causes the undefined problem. Here is my code:
var superBlinders = [ ["Firestorm", 4000], ["Solar Death Ray", 6000], ["Supernova", 12000] ];
var lighthouseRock = {
gateClosed: true,
weaponBulbs: superBlinders,
capacity: 30,
secretPassageTo: "Underwater Outpost",
numRangers: 0
};
function addRanger(location, name, skillz, station) {
location.numRangers++;
location["ranger" + location.numRangers] = {
name: name,
skillz: skillz,
station: station
};
}
addRanger(lighthouseRock, "Nick Walsh", "magnification burn", 2);
addRanger(lighthouseRock, "Drew Barontini", "uppercut launch", 3);
addRanger(lighthouseRock, "Christine Wong", "bomb defusing", 1);
var dontPanic = function () {
var message = "Avast, me hearties!\n";
message += "There be Pirates nearby! Stations!\n";
for (var i = 1; i <= lighthouseRock.numRangers; i++) {
var thisRangerNumber = i;
var thisRanger = "ranger" + thisRangerNumber;
// message += lighthouseRock.ranger1.name + ", man the " + superBlinders[lighthouseRock.ranger1.station][0] + "!\n";
message += lighthouseRock.thisRanger.name + ", man the " + superBlinders[lighthouseRock.thisRanger.station][0];
};
console.log(message);
}
The expected output should look something like this:
Avast, me hearties!
There be Pirates nearby! Stations!
<name>, man the <superblinder>!
<name>, man the <superblinder>!
<name>, man the <superblinder>!
How can I insert thisRanger into my code so that it gives me the expected output? Thank you very much for your help!

Working code!
It outputs all you want it todo!
UPDATE you have an error in your code I fixed that also..
Ranger2 will always be stationed on undefined since there aren't 3 stations when counting as an array, remember array in javascript starts counting from 0(zero). I changed Drew barontini to "0"
addRanger(lighthouseRock, "Nick Walsh", "magnification burn", 2);
addRanger(lighthouseRock, "Drew Barontini", "uppercut launch", 0);
addRanger(lighthouseRock, "Christine Wong", "bomb defusing", 1);
CODE OUTPUT
Avast, me hearties!
There be Pirates nearby! Stations!
Nick Walsh, man the Supernova,12000 Drew Barontini, man the Firestorm,4000Christine Wong, man the Solar Death Ray,6000
I didn't do much to change your code. But what I did is that I change your code into
message += lighthouseRock[thisRanger].name + ", man the " + superBlinders[lighthouseRock[thisRanger].station] +"\n";
Its important to know with javascript that you can use brackets [] to get to an object property if you build the stirng dynamicly.
var superBlinders = [ ["Firestorm", 4000], ["Solar Death Ray", 6000], ["Supernova", 12000] ];
var lighthouseRock = {
gateClosed: true,
weaponBulbs: superBlinders,
capacity: 30,
secretPassageTo: "Underwater Outpost",
numRangers: 0
};
function addRanger(location, name, skillz, station) {
location.numRangers++;
location["ranger" + location.numRangers] = {
name: name,
skillz: skillz,
station: station
};
}
addRanger(lighthouseRock, "Nick Walsh", "magnification burn", 2);
addRanger(lighthouseRock, "Drew Barontini", "uppercut launch", 0);
addRanger(lighthouseRock, "Christine Wong", "bomb defusing", 1);
var dontPanic = function () {
var message = "Avast, me hearties!\n";
message += "There be Pirates nearby! Stations!\n";
for (var i = 1; i <= lighthouseRock.numRangers; i++) {
var thisRangerNumber = i;
var thisRanger = "ranger" + thisRangerNumber;
// message += lighthouseRock.ranger1.name + ", man the " + superBlinders[lighthouseRock.ranger1.station][0] + "!\n";
message += lighthouseRock[thisRanger].name + ", man the " + superBlinders[lighthouseRock[thisRanger].station] +"\n";
};
console.log(message);
}
dontPanic();

Related

Alerting data specifics inside array

I'm running into a javascript beginner's problem. I have this data stored in an array, and I'm trying to alert the data to see if it checks out.
I want to alert myself the average of the distance of all, not both planets even though both is all in this case, but I eventually want to have an array that keeps a lot more than just two. Right now, it just alerts the distance of the last record in the array list, which is weird. I thought it'd be an average for all.
Also, how do I program the least and highest numbers of the "Distance" property in the array, and then alert the "Host name" with it. So, if I have a button and I click on "Closest", the Host name of the lowest number in "Distance [pc]" will be alerted. I only need an example of the code for "Distance", so I'll know how to do the same for all other variables.
Thank you if you're willing to help out!
Btw, the list is JSON data. Maybe important to mention this.
// this array holds the json data, in this case stastics of exoplanets retrieved from nasa's website
var arr= [ {
"rowid": 684,
"Host name": "K2-15",
"Number of Planets in System": 1,
"Planet Mass or M*sin(i)[Jupiter mass]": null,
"Planet Radius [Jupiter radii]": 0.221,
"Planet Density [g": {
"cm**3]": null
},
"Distance [pc]": 437,
"Effective Temperature [K]": 5131,
"Date of Last Update": "7/16/2015"
},
{
"rowid": 687,
"Host name": "K2-17",
"Number of Planets in System": 1,
"Planet Mass or M*sin(i)[Jupiter mass]": null,
"Planet Radius [Jupiter radii]": 0.199,
"Planet Density [g": {
"cm**3]": null
},
"Distance [pc]": 134,
"Effective Temperature [K]": 4320,
"Date of Last Update": "7/16/2015"
}];
//every record is put in a variable
var rowid;
var hostName;
var numberOfPlanetsInSystem;
var planetMass;
var planetRadius;
var distance;
var effectiveTemperature;
for(var i=0;i<arr.length;i++){
rowid= arr[i]["rowid"];
hostName= arr[i]["Host name"];
numberOfPlanetsInSystem= arr[i]["Number of Planets in System"];
planetMass= arr[i]["Planet Mass or M*sin(i)[Jupiter mass]"];
planetRadius= arr[i]["Planet Radius [Jupiter radii]"];
distance= arr[i]["Distance [pc]"];
effectiveTemperature= arr[i]["Effective Temperature [K]"];
};
//alert to test it out
alert(distance);
let totalDistance = maxDistance = 0;
let minDistance = arr[0]["Distance [pc]"];
let closestHost = farthestHost = "";
for(let i = 0; i < arr.length; i ++) {
totalDistance += arr[i]["Distance [pc]"]
if (arr[i]["Distance [pc]"] < minDistance) {
minDistance = arr[i]["Distance [pc]"];
closestHost = arr[i]["Host name"];
}
if (arr[i]["Distance [pc]"] > maxDistance) {
maxDistance = arr[i]["Distance [pc]"];
farthestHost = arr[i]["Host name"];
}
}
let meanDistance = totalDistance/arr.length;
In your cycle you are always overwrite your variable distance, not adding them.
Use distance += arr[i]["Distance [pc]"]
+= measn distance = distance + arr[i]["Distance [pc]"]
EDIT
Here is a working jsFiddle
You need to init var distance = 0;
var distance = 0; //Important!
var arr = [{
"rowid": 684,
"Host name": "K2-15",
"Number of Planets in System": 1,
"Planet Mass or M*sin(i)[Jupiter mass]": null,
"Planet Radius [Jupiter radii]": 0.221,
"Planet Density [g": {
"cm**3]": null
},
"Distance [pc]": 437,
"Effective Temperature [K]": 5131,
"Date of Last Update": "7/16/2015"
},
{
"rowid": 687,
"Host name": "K2-17",
"Number of Planets in System": 1,
"Planet Mass or M*sin(i)[Jupiter mass]": null,
"Planet Radius [Jupiter radii]": 0.199,
"Planet Density [g": {
"cm**3]": null
},
"Distance [pc]": 134,
"Effective Temperature [K]": 4320,
"Date of Last Update": "7/16/2015"
}];
for (var i = 0; i < arr.length; i++) {
distance += arr[i]["Distance [pc]"];
};
alert('Total distance: ' + distance + "\n" + 'Number of planets: ' + arr.length + "\n" + 'Average: ' + distance / arr.length);

Is it possible to pass object as parameter?

var obj = {
name1: 1,
name2: 2
}
function myF(obj) {
console.log(obj.name1) // by idea it must return 1
};
myF(obj)
Does anybody know how to pass object in function?
Yes objects make great parameters.
var p1 = {
name: "Tom",
age: 23,
isMale: true
};
var p2 = {
name: "Alicia",
age: 21,
isMale: false
};
var p3 = {
name: "Landon",
age: 1,
isMale: true
};
function greeting(person) {
var str = '';
str += 'Hello my name is ';
str += person.name + ' ';
str += 'I'm a ' + person.age + ' year old ';
if (person.isMale) {
str += age > 18 ? 'man' : 'boy';
} else {
str += age > 18 ? 'woman' : 'girl';
}
if (person.age < 3) {
str = 'Bah'
}
console.log(str);
};
greeting(p1); // 'Hello my name is Tom I'm a 23 year old man';
greeting(p2); // 'Hello my name is Alicia I'm a 21 year old woman;
greeting(p3); // 'Bah';
Objects are good for when you have a grouping of values that belong together and you don't want to pass them in individually (If they belong together they rarely should be passed on their own.)
This is very common practice. Many libraries will utilize a config object so one does not have to specify multiple params
Example:
function makeSquare(height, width, color, border)
Could be easier represented with
function makeSquare(config)
This would make it easier for users to leave out some parameters, say you wanted to makeSquare without a border you would not need to include the border param if you are passing and object.
With parameters
makeSquare(10, 20, red, null)
with Obj
config = {
height: 10,
width: 10,
color: 'red'
};
makeSquare(config);
If you had an extensive amount of configuration options you could see where this may save quite a bit of development time and space

make a listing function for a array Jquery / Javascript

so..
var songList = ["1", "2" ,"3","4","5","6","7","8","9","10"];
so my idea is to make a function which returns the first 5 Set of the values according to the index.
if
getList("1"); // is called.
it should result in "1 2 3 4 5" output.
and if
getList("2"); // is called
it should result in " 6 7 8 9 10"
It seems you need something like this:
var songList = ["01R!Wagner=_W!_March.mid ", "1004. score.mid ", "1005. yanni-one mans dream.mid ", "1006. haggstrom.mid ", "1007. la campanella pi.mid ", "1008. chp op18.mid ", "1009. Avicii - Wake Me Up.mid ", "101. Titanic my-heart will go on.mid ", "1010. 3intro.mid ", "1011. cast int.mid ", "1012. Action52Cheetahmen.mid ", "1013. pinkband.mid ", "1014. goldendreams.mid ", "1015. Reflections Of A Passion (Yanni).mid ", "1016. Nostalgia (Yanni).mid ", "1017. Rozen Maiden - Kinjirareta Asobi.mid ", "1018. Triple baka.mid ", "102. Konduktor.mid ", "1020. kraftwerk-franz schubert.mid ", "1021. naruto shippuuden - Blue Bird.mid ", "1022. naruto shippuuden - DIVER.mid ", "1023. dire-dire-docks-arranged-.mid ", "1024. koopa-s-theme.mid ", "1025. theme.mid ", "1026. the-last-spartan.mid ", "1027. xbox-startup-sequence.mid ", "1028. sml1-1.mid ", "1029. fourside1.mid ", "103. Minecraft - Sweden.mid ", "1030. eb hotel.mid ", "1031. smoke.mid ", "1032. whoboss.mid ", "1033. entrtanr.mid ", "1034. Eiffel 65- I'm blue (dabadee).mid "];
function makeList(index) {
var start = Math.max(0, (index-1)*5), // to avoid negative indexes
end = Math.min(index*5, songList.length); // to avoid out-of-bound
return songList.slice(start, end);
}
How about this
var songList = ["song_1.mp3","song_2.mp3",
"song_3.mp3","song_4.mp3",
"song_5.mp3","song_6.mp3",
"song_7.mp3","song_8.mp3"]
function makeList(index){
var songsLength = songList.length;
var num_songs = (index+5);
var next_songs = [];
if (num_songs > songsLength){
console.log("cant select index that is greater than length");
} else {
for(var i = index; i < num_songs;i++ ){
next_songs.push(songList[i]);
}
return next_songs;
}
}
You can pass any index to start from your list. with num_songs you can change how many songs you want to return. Remember that the index starts at 0, so if you want to be able to pass makeList(1) to return the first element, you could also set for (var i = (index-1); i < songsLength; i++)
makeList(3) will return the same as songList.slice(3, 8)
Check the fiddle

Map object into array then output value with jQuery

I have the below javascript which puts a list of customers into an object, then outputs then on the page.
var name = ["andrew", "vic", "casey"];
var job = ["builder", "baker", "dentist"];
var product = [111, 222, 111];
var qty = [1, 2, 3];
var data = {};
for (i = 0; i < name.length; i++) {
a = {
"name": name[i],
"job": job[i],
"product": product[i],
"qty": qty[i]
};
a['xtra-' + product[i]] = qty[i];
data[name[i]] = a;
console.log(a);
}
data = $.map(data, function (val, key) {
return val;
});
data.sort();
$.each(data, function (i, val) {
$('body').append(val.name + ' - ' + val.job + ' - ' + val.product + ' - ' + val.qty + ' - ' + (val.xtra + val.product) + '<br>');
});
With what I have so far see fiddle, I am outputting the persons name - job - product - qty.
andrew - builder - 111 - 1 - NaN<br>
vic - baker - 222 - 2 - NaN<br>
casey - dentist - 111 - 3 - NaN<br>
I am also trying to print out some extra information which is storred in my object called 'xtra-' + product[i].
This is being storred in a as you can see from the console log eg xtra-222 however, I can't get it outputting in my each statement?
I understand what I have done
val.xtra + val.product
is trying to add a number with a string and this is why it isn't working but I can't seem to get work out what syntax is required (possibly getting the last nth item) here or maybe there is another method to acheive what I want here?
In case there is any confusion I want my output to be
andrew - builder - 111 - 1 - 1
vic - baker - 222 - 2 - 2
casey - dentist - 111 - 3 - 3
Where the last 1,2,3 comes from the value 'xtra-' + product[i] stored in a
The problem is inside the .each loop, more specifically in (val.xtra + val.product).
The val object for the first run of that loop is:
Object {name: "andrew", job: "builder", product: 111, qty: 1, xtra-111: 1}
As you can see, there's no xtra key in that object, instead you have an xtra-111 key. So if you use (val['xtra-' + val.product] + val.product) you'll get the result that you need.
Here's the fixed code http://jsfiddle.net/VdVax/
in your $.each did you mean
val["xtra-" + val.product]
?
Here is a working fiddle http://jsfiddle.net/p5Zhc/3/

First Javascript program. What am I doing wrong?

I have finally gotten around to creating my first little practice program in Javascript. I know it's not elegant as it could be. I have gotten most of this code to work, but I still get an "undefined" string when I run it a few times. I don't know why. Would someone be kind enough to explain to me where this undefined is coming from?
var work = new Array();
work[1] = "product design";
work[2] = "product system design";
work[3] = "product social media post x5";
work[4] = "product Agent Recruitment system design";
work[5] = "product profile system design";
work[6] = "product Agent testing design";
work[7] = "product customer support";
work[8] = "product promotion";
var course = new Array();
course[1] = "javascript";
course[2] = "mandarin";
course[3] = "javascript practical-Code Academy";
course[4] = "javascript practical-learn Street";
course[5] = "mandarin practical-memrise";
course[6] = "new stuff with audiobooks";
var activity = new Array();
activity[1] = "listen to podcasts";
activity[2] = "chat online";
activity[3] = "Exercise";
activity[4] = "take a walk";
activity[5] = "call a friend";
var picker1 = Math.floor(Math.random()*3+1);
var picker2 = Math.floor(Math.random()*work.length+1);
var picker3 = Math.floor(Math.random()*course.length+1);
var picker4 = Math.floor(Math.random()*activity.length+1);
var group_pick = function(){
if(picker1 === 1){
return "Time to work on ";
} else if(picker1 === 2){
return "Time to learn some ";
} else if (picker1 === 3){
return "Lets relax and ";
} else {
return "error in group_pick";
}
};
var item_pick = function() {
if (picker1 === 1) {
return work[picker2] ;
} else if (picker1 === 2) {
return course [picker3] ;
} else if (picker1 === 3) {
return activity[picker4] ;
} else {
return "error in item_pick";
}
};
var task = group_pick() + item_pick();
document.write(task);
Array's start with an index of zero. When you assign a value to the 1 index, a 0 index is created you, with no value (undefined).
var arr = new Array();
arr[1] = 'hi!';
console.log(arr); // [undefined, "hi!"]
console.log(arr.length) // 2
Length is 2, check that out. You thought you had one item in that array but length is 2.
Usually it's easier to not manage the array indices yourself. And the array literal syntax is usually preferred for a number of reasons.
var arr = [];
arr.push('hi!');
console.log(arr); // ["hi!"]
console.log(arr.length) // 1
Or just create the array with the items in it directly, very handy.
var arr = [
"hi",
"there!"
];
console.log(arr); // ["hi", "there"]
console.log(arr.length) // 2
Once you are making the arrays properly, you can get a random item with simply:
var arr = ['a','b','c'];
var index = Math.floor(Math.random() * arr.length);
console.log(arr[index]); // "a", "b" or possibly "c"
This works because var index will be calculated by a random value of between 0.0 and up to but not including 1.0 times 3 (the length of the array). Which can give you a 0, 1 or a 2.
So this arr right here, has 3 items, one at 0, one at 1, and one at 2.
Learning to address arrays from zero can be mentally tricky. You sort of get used to it. Eventually.
A working example using these tips here: http://jsfiddle.net/du5Jb/
I changed how the arrays are declared, and removed the unneeded +1 from var pickerX calculations.
The problem is that the .length attribute for arrays counts the number of elements in the array starting from zero. So for example activity has elements 1 through 5, so according to Javascript the .length is actually 6. Then your random number calculation will choose a number from 1 through 7, past the end of the array. This is where the undefined comes from.
You can fix this by starting your index numbering at 0 instead of 1, so activity would have elements 0 through 4, with a .length of 5. Also remove the +1 from your choice calculations.
When you use your "pickers", you don't want to have the +1 inside of the `Math.floor functions.
Consider this array:
var array = [ "one", "two", "three" ];
array.length; // 3
The length is 3 -- makes sense, there are 3 items inside.
But arrays are zero-based.
array[0]; // "one"
array[1]; // "two"
array[2]; // "three"
array[3]; // undefined
So when you add that + 1, you're:
a) making it impossible to pick the first thing in the array
b) making it possible to pick a number that is exactly 1 higher than the last element in the array (undefined)
The problem here as i see it is that when you generate your random variables you're doing PickerX + 1...
So the right way to do it would be PickerX without the +1.
Also Off topic you shouldn't use if commands, try using switch case...
Here's the fixed code-
var work = new Array()
work[0] = "product design";
work[1] = "product system design";
work[2] = "product social media post x5";
work[3] = "product Agent Recruitment system design";
work[4] = "product profile system design";
work[5] = "product Agent testing design";
work[6] = "product customer support";
work[7] = "product promotion";
var course = new Array();
course[0] = "javascript";
course[1] = "mandarin";
course[2] = "javascript practical-Code Academy";
course[3] = "javascript practical-learn Street";
course[4] = "mandarin practical-memrise";
course[5] = "new stuff with audiobooks";
var activity = new Array();
activity[0] = "listen to podcasts";
activity[1] = "chat online";
activity[2] = "Exercise";
activity[3] = "take a walk";
activity[4] = "call a friend";
var picker1 = Math.floor(Math.random() * 3 +1 );
var picker2 = Math.floor(Math.random() * work.length );
var picker3 = Math.floor(Math.random() * course.length );
var picker4 = Math.floor(Math.random() * activity.length );
var group_pick = function(){
switch(picker1){
case 1:
return "Time to work on ";
case 2:
return "Time to learn some ";
case 3:
return "Lets relax and ";
default:
return "error in group_pick";
}
};
var item_pick = function() {
switch(picker1){
case 1:
return work[picker2] ;
case 2:
return course [picker3] ;
case 3:
return activity[picker4] ;
default:
return "error in item_pick";
}
};
var task = group_pick() + item_pick();
document.write( task );​
Don't work so hard. Zero is your friend. Let's go golfing...
var work = [
"product design", "product system design",
"product social media post x5",
"product Agent Recruitment system design",
"product profile system design",
"product Agent testing design",
"product customer support", "product promotion",
], course = [
"javascript", "mandarin",
"javascript practical-Code Academy",
"javascript practical-learn Street",
"mandarin practical-memrise", "new stuff with audiobooks",
], activity = [
"listen to podcasts", "chat online", "Exercise",
"take a walk", "call a friend",
];
function rint(cap) {
return (Math.random() * cap) | 0;
}
function pick(item) {
switch (item) {
case 0: return "Time to work on " +
work[ rint(work.length) ];
case 1: return "Time to learn some " +
course[ rint(course.length) ];
case 2: return "Lets relax and " +
activity[ rint(activity.length) ];
default: return "error";
}
}
document.write(pick(rint(3)) + '<br>');

Categories

Resources