If I have this object:
var myclass = {
foo: {
bar: function(var) {}
},
some: {
bar: function(var) {}
}
}
and I want to call the bar function depending on a variable that defines the parent level of the object like this:
var part = "some";
myclass.part.bar(var);
How can I do?
You can do it using array access notation:
myclass[part].bar(var);
JavaScript objects are like associative arrays, and you can use a property name to either set or get the property's value, you can even create new properties with this syntax.
For example:
var obj = { a : 1 };
console.log(obj["a"]); // 1
obj["b"] = 2; // this creates a property called b and assigns 2 as the value
console.log(obj["b"]); // 2
You can keep a reference to a function as a variable, which is a little cleaner than a string.
var func = myclass.foo.bar;//or myclass.some.bar
...
func.call(myclass, var);
Or keep a reference to the part:
var part = myclass.foo;//or myclass.some
part.bar.call(myclass, var);
Related
I'm sure there is a simple way to do this, but am stumped for now.
I have many variables defined at the top of my script (here is an example of two):
var firstVar,secondVar;
Then I have an object which contains those variables:
var myObj = { a: {name:firstVar, number:1}, b: {name:secondVar, number:2}
I want to assign values to those variables:
keys = Object.keys(myObj);
function getAll(e){
var myArray = [];
for (var prop in myObj){
myArray.push(myObj.prop[e]);
}
return myArray;
}
The behaviour I want is:
var nameVars = getAll(name);
// [firstVar,secondVar]
But instead it returns:
// [undefined,undefined]
How else can I get the variables before defining them?
Then I have an object which contains those variables:
No, it doesn't. It contains a copy of the value those variables contained as of when you created the object (which is undefined, since you've never assigned a value to them). Once created, there is no ongoing link between the object property you've copied the value to and the variable.
Since the object has no enduring link to the variables, there's no way for getAll to return the information you've said you want.
You've said in a comment that you're building d3 graphs and have the same structure with some variables, and want to avoid repeating yourself. It sounds to me like you want a builder function:
function buildObject(firstVar, secondVar) {
return { a: {name:firstVar, number:1}, b: {name:secondVar, number:2} };
}
...which you would then use like this:
var obj1 = buildObject("value1", "value2");
// do a graph
var obj2 = buildObject("valueA", "valueB");
// do a graph
...or possibly even something that just takes the variables and produces the graph:
function makeGraph(firstVar, secondVar) {
buildTheGraph({ a: {name:firstVar, number:1}, b: {name:secondVar, number:2} });
}
I don't think it is, but if it's the names you want, just put them in quotes (and also myArray.push(myObj.prop[e]); should be myArray.push(myObj[prop][e]); and getAll(name) should be getAll("name")), but again there's no link to the variables at all:
// Since they're not used, we don't even need these: var firstVar, secondVar;
var myObj = { a: { name: "firstVar", number: 1 }, b: { name: "secondVar", number: 2 } };
function getAll(e) {
var myArray = [];
for (var prop in myObj) {
myArray.push(myObj[prop][e]);
}
return myArray;
}
var nameVars = getAll("name");
console.log(nameVars);
...but note that having the names doesn't help you get the variable values later (unless you use eval, which you should seek to avoid).
I am trying to access an object but the name is variable. So:
I have object41, object42 and object43. I want to access object42.
id = 42;
something like this:
object+id.function();
I have searched and found how to assign objects with variable names and how to access properties with variable names but I can't figure out how to access objects with variable names.
Is this something obvious that I am missing?
If these objects are global, you can access them via the window object, and then call your function on the resulting object.
var id = 42;
window["object" + id].function();
Try using eval
// Sample object
function X(id) {
this.value1 = "A" + id;
this.function = function f(value){
alert(value);
};
return this;
}
// n number of object created
var object1 = new X(1);
var object2 = new X(2);
// iterate over all object
for (i=1; i<=2; i++) {
var expr = "object"+i+".function(object"+i+".value1)";
eval(expr);
}
Here a jsfiddle : demo
Can someone explain what is happening in the code below? I'd expect toString to get called for either both foo and bar, or neither. How is literal object notation different from adding fields to an object after it is created?
function Obj(v) {
this.v = v;
};
Obj.prototype.toString= function() {
window.alert("to string called for " +
this.v);
return this.v.toString();
}
var foo = new Obj('foo');
var bar = new Obj('bar');
// toString is not called here.
var map = {foo : 'blah'};
// toString is called here.
map[bar] = "blah2";
Why do object literals not use toString() while adding to an existing object does use toString()?
http://jsfiddle.net/pByGJ/2/
The main reason that object literals don't evaluate the identifier to the left of the colon is so you're not force to quote all literal names (as you do in JSON).
Bracket notation forces you to quote property names, if you don't, it will be evaluated as a variable.
The reason toString() does get called in the second example is because bar has to be converted to a string to be used as a property name.
In your first example, you're just creating a literal object (that is the exactly the same as {"foo" : 'blah'}). So that is never using the variable foo
If you want to create an object using a variable name, you can't use literal object notation, you have to use [] which is what forces it to call toString()
Here's a function to create objects with variable names in one expression.
function obj(key, value /*, key, value, ... */) {
var obj = {};
for (var i = 0, ln = arguments.length ; i < ln; i+=2) {
obj[arguments[i]] = arguments[i+1];
}
return obj;
}
Clearer Example
The fact that your variable names and values are the same doesn't help understanding the problem. Let me suggest this code
var foo = new Obj('fooValue');
var bar = new Obj('barValue');
var map = {foo : 'blah'};
map[bar] = "blah2";
// You expect map to be {fooValue: 'blah', barValue: 'blah2'}
// But it's {foo: 'blah', barValue: 'blah2'}
To do what you need, use my obj function
// Almost as clear as literal notation ???
var map = obj(
foo, 'blah',
bar, 'blah2'
);
// map = {fooValue: 'blah', barValue: 'blah2'} Yay!!
keys in an object literal are taken as strings, not interpreted as variables. This:
var map = {foo : 'blah'};
is equivalent to this:
var map = {"foo" : 'blah'};
and this:
var map = {};
map["foo"] = "blah";
but is completely different than this:
var map = {};
map[foo] = "blah";
var User = Parse.User.extend({
// instance members
}, {
// types
TYPE_TRAINER : 1,
TYPE_ATHLETE : 2,
types: {
TYPE_TRAINER : 'Trainer',
TYPE_ATHLETE : 'Athlete'
}
});
I want to have TYPE_TRAINER and TYPE_ATHLETE maintain the values of 1 and 2 as defined prior to the types object so that I can use the types object in a template.
If you don't know about Parse, Parse.User is an extension of Backbone.Model.
Thanks!
What you're asking is not directly possible in JavaScript object literals. Object literals are always a literal value on the left hand / key side.
The closest you could get is to use the TYPE_TRAINER and TYPE_ATHLETE keys as variables to assign values via the square bracket syntax for accessing object key/value pairs:
var a = 1;
var b = 2;
var obj = {};
obj[a] = "a";
obj[b] = "b";
This will result in the obj object looking like this:
{
1: "a",
2: "b"
}
So you could do something like this, to get what you want in your code:
var userMethods = {
// types
TYPE_TRAINER : 1,
TYPE_ATHLETE : 2
};
userMethods[userMethods.TYPE_TRAINER] = 'Trainer';
userMethods[userMethods.TYPE_ATHLETE] = 'Athlete';
var User = Parse.User.extend({
// instance members
}, userMethods);
It's more code than you probably want, but it's the only way to achieve what you want because of the object literal syntax.
The Parse.Object Javascript documentation says:
You should call either:
var MyClass = Parse.Object.extend("MyClass", {
// Instance properties
}, {
// Class properties
});
or, for Backbone compatibility:
var MyClass = Parse.Object.extend({
className: "MyClass",
// Other instance properties
}, {
// Class properties
});
If you are wanting to extend the Parse.User "class" (it's an object, not a class), you need to include the className as described above because Parse.User is itself an extension of Parse.Object.
If I have a variable foo that hold a reference to an object:
var foo = someObj;
How can I then use the name of the object as a string?
I tried:
var bar = foo.valueOf()
But that just returned another reference to the object.
What I have is an algorithm that selects from a large number of objects. I then want to use the name of that object to select from amongst a group of HTML elements. Using the following does not work either (returns null):
document.getElementById(foo)
Thank you.
There is no reliable way to get the name of the object.
Example:
var obj = {};
var obj1 = obj;
var obj2 = obj;
magically_get_and_print_name(obj); // What to print? "obj"? "obj1"? "obj2"?
Methods to get the name in some cases:
Function declarations - funcreference.name (non-standard, though well-supported)
Constructor instances - instance.constructor.name
Let's say you have:
var someObj = {
a: 15,
b: 36
};
And then you did:
var foo = someObj;
There's no way to get the string "someObj" (or "foo") from foo.
What you could do, is add the name to the object when creating it. Something like this:
var someObj = {
a: 15,
b: 36,
objName: 'someObj'
};
var foo = someObj;
console.log(foo.objName); // "someObj"