Accessing an array by index within an object - javascript

I'm trying to access a particular array by it's index within an object within an object (sorry, this may be the wrong terminology).
var person = {
name: ["Tom", "Mike", "Sally"],
hair: {
style: ["bob", "weave", "mullet"],
length: ["long","short","medium"]
}
}
getDetail(length);
function getDetail(det) {
var answer = person.hair.det[1];
console.log("Hair " + det + " is " + answer) //outputs: "Hair length is long"
}
When I do this, I am getting an error of "Can't read property '1' of undefined". Which tells me it isn't passing the 'det' variable correctly. If I take that out and put length instead, it works.
What am I missing?
Thanks!

The problem is that in your case you should be passing a string or a variable to your getDetail() function (length by itself is none, as it is not defined previously, nor is quoted), also there's the fact that if you want to use a variable to indicate the property/key of an object, you should use this type of syntax: object["property"]. You can change your code to:
getDetail('length');
function getDetail(det) {
var answer = person.hair[det][1];
console.log("Hair " + det + " is " + answer) //outputs: "Hair length is long"
}

When you say getDetail(length), that's looking for a variable called length, and passing it into the function. Since it doesn't exist, the function gets undefined.
HOWEVER, when you write "myObjectVariableName.etcetera", it will specifically look for an index called "etcetera" - so it won't even be using your det argument - it's instead looking for the "det" index.
You can, instead, write either of the following.
myObjectVariableName["myIndexName"]
var myString = "myIndexName";
myObjectVariableName[myString]
Both of those will both have the same result.
So, to get the expected result, what you want to do is pass the string "length" into getDetail, and then replace .det with [det] (darkajax seems to have written what I was going for, but I'm hoping my explanation also helps make sense of why it wasn't working)

Related

Give eval a value in JavaScript

very basic JavaScript programmer here!
I was busy on some code with variables that look like this:
blocktype1;
blocktype2;
blocktype3;
blocktype4;
... //everything between blocktype4 and blocktype70, the three dots are not actual code!
blocktype70;
Now I was using eval() in a function where a value was given to one of the blocktype variables. The blocktype depended on the variable "number".
This is what I had for that part:
eval("blocktype" + number) = 3
What I want is, say "number" is 27, then I want the variable blocktype27 to get a value of 3.
When I check the console it says:
ReferenceError: Invalid left-hand side in assignment
Could anyone possibly help me?
I would prefer just vanilla JavaScript and still the use of eval.
Thank you for your time!
The 'correct' solution would probably be to use an Array which is ideal for sequences and are accessible by index.
var number = 1;
var val = 3;
var blocktype = []; // so clean
blocktype[number] = val;
However, properties can be accessed as with the bracket notation as well. This assumes the variables are in global scope and are thus properties of the global (window) object.
var blocktype1; // .. etc
window["blocktype" + number] = val;
The problem with the eval is that is effectively the same as doing f() = 3 which does not make sense: only variables/properties can be assigned to1.
However eval is a built-in function and the results of a function cannot be assigned to, per the error message. It could be written as
var blocktype1; // .. etc (see dandavis' comment)
eval("blocktype" + number + " = " + val);
// What is actually eval'd is:
// eval("blocktype1 = 3")
which quickly exposes a flaw with eval. If val was the string "Hello world!" with would result in eval("blocktype1 = Hello world!") which is clearly invalid.
1 For the gritty: the left-hand side of an assignment has to be a Reference Specification Type, which is a more wordy way of describining the above behavior. (It is not possible for a JavaScript function to return a RST, although it could technically be done for vendor host objects.)
Feel free not to accept this, since it's specifically not using eval(), but:
You can allocate an array of size 71 like so:
var blocktype = new Array(71);
(your number values apparently start at 1, so we'll have to ignore the first element, blocktype[0], and leave room for blocktype[70], the 71st)
You can now assign elements like this:
blocktype[number] = 3;
and use them like so:
alert( blocktype[number] );

Dynamic property name concatenation

I'm looking for an easy way to assign to a variable depending on the value of another variable.
device.slot2_clipList[clipNumber] = singleClipDetails;
what I'm trying to do is: replace the "2" with another variable, so that i can run the same operation while just changing the
var slotNumber, and write to the corresponding variable.
i tried
device.slot + device.slotNumber + _clipList[clipNumber]
but (obviously?), this doesn't work.
How can this be done? (Maybe I named the Question incorrectly, but that was the closest I could think of.)
Thanks
This is what bracket notation is for
var i = 2;
device['slot' + i + '_clipList'][clipNumber] = singleClipDetails;
device['slotNumber' + _clipList[clipNumber] ]
Explanation:
foo.bar in javascript is identical (even in performance) to foo['bar']. So any object property name can be built up from strings.

creating variable names from parameters in javascript

I was wondering if it is possible to create variable names from parameters passed to a function in javascript. Something like this:
function createVar(number) {
var "number" + number;
}
createVar(1)
I'm new to Stack Overflow and programming, so any help would be appreciated.
You could attach this to the window object, but note it will be global. For example:
function createVar(varName, value) {
window[varName] = value;
}
createVar("test", "Hello World");
alert(test); // Outputs "Hello World".
It is possible to interpret Object as associative array where you specify index and get value by name of index ( hash ):
var x = Array();
x[number] = value;
Single variable name is for programmer, and the code would be hard to maintain and understand when you set variable dynamically in code.
Honestly, I don't see why this would ever be useful, because every time you want to use the variable you'd have to search for it with your number argument.
However, you can do it, albeit not the exact way you had described:
function createVar(number){
eval("var number" + number.toString() + ";");
}
however, this variable will only be accessible within the function, to make it global assign to the window object:
function createVar(number){
window["number" + number] = 15; // creates "global" variable
}
As I've stated before, however, I don't see this being useful, [i]ever[/i], if you want to stratify values by numbers you'd be much better off with an array.

Accessing nested objects in javascript

I am trying to run some JavaScript, but it is not working.
I have an object with two properties that are also objects.
var people = {
me: {
name: "Hello"
},
molly: {
name: "Molly"
}
};
And I am trying to make a function that uses a for/in statement and an if statement to list the properties of people.
var search = function (x) {
for (var a in people) {
if (people.a.name === x) {
return people.a;
}
}
};
So the function loops through the properties of people and assigns them to the variable a. Therefore people.a will be equal to a property of people. Then the function returns the property (people.a).
So if I type in me as parameter x, will the function should return the properties for the me object? I put this code in jsLint and jsHint and it passed, but I decided to remove the corrections because they were useless.
I then want to print the object properties in the browser:
var print = search("me");
document.getElementById("p").innerHTML(print);
I have this linked to an html document, with a tag id "p". I have tested javascript in the html document already, so I know that the javascript document is linked properly.
But the code will not work. Does anyone have any suggestions?
I have it working now thanks to the answers. But I thought that it would only print "Hello" to the screen, not { name: "Hello"}.
You need to use people[a], not people.a. The former looks for a property with the name of the value stored in a; the latter looks for a property literally named "a", which of course doesn't exist.
for (var a in people) {
if (people[a].name === x) {
return people[a];
}
}
Fiddle here.
Also, I think you meant search("Hello"), right? If not, then it would just be var search = function(x) { return people[x]; }.
people.a.name
you need to use the bracket operator if you want to access an item by name. Using people.a is literally searching for a member named 'a' instead of a member with the same name as the value of a.
Try:
people[a].name
instead.
4 errors in your code:
replace people.a with people[a]
replace innerHTML() with innerHTML
set HTML like this: document.getElementById("p").innerHTML = print.name;
As in a previous answer, search by name
Code: http://jsfiddle.net/nabil_kadimi/vVSPG/

Javascript: String concatenation in object constructor

Been trying to create a JavaScript object member that always contains a common string. Whenever I create a new object, instead of concatenating the string, it overwrites it with the passed value on creation. If it matters (I don't think it does) the string contains numbers. Par example:
function myObj(strToConcat){
this.combinedString = "Hello " + strToConcat, /* have used + and .concat() without success */
}
var newObj = new myObj("1.2.3");
console.log(newObj.combinedString); /* says "1.2.3", the leading "Hello " is absent */
Can't seem to get this to concatenate the strings.
EDIT: I apologize, the error was outside the code that I thought responsible. Disregard please. My apologies.
You have error in your reference
console.log(myObj.combinedString);
should be
console.log(newObj.combinedString);
Running your code gives me SyntaxError: Unexpected token }. Replace the , at the end of the second line with a ; and I get the expected result of "Hello 1.2.3".

Categories