As mentioned in MDN, Property names must be strings.
For code,
var foo = {unique_prop: 1}, obj = {};
obj[foo] = 'value';
console.log(obj[foo]);
In MDN, it says,
In the SpiderMonkey JavaScript engine, this string would be "['object Object']".
How does the property(string literal) of object type obj is stored like?
Is the property stored as "['unique_prop 1']" ?
When you create a property on an object from a variable, JS engine calls toString() method on a passed value. The actual value for the key is decided from its type.
You can check this behaviour yourself:
var foo = {};
foo.toString = function() {
return "toString";
}
var bar = {};
bar[foo] = "prop value";
for (var k in bar) {
console.log(k);
}
Related
This question already has answers here:
Add a property to a JavaScript object using a variable as the name? [duplicate]
(14 answers)
Closed 7 years ago.
I want to add a new property to 'myObj', name it 'string1' and give it a value of 'string2', but when I do it it returns 'undefined:
var myObj = new Object;
var a = 'string1';
var b = 'string2';
myObj.a = b;
alert(myObj.string1); //Returns 'undefined'
alert(myObj.a); //Returns 'string2'
In other words: How do I create an object property and give it the name stored in the variable, but not the name of the variable itself?
There's the dot notation and the bracket notation
myObj[a] = b;
ES6 introduces computed property names, which allow you to do
var myObj = {[a]: b};
Dot notation and the properties are equivalent. So you would accomplish like so:
// const myObj = new Object();
const myObj = {};
const a = 'string1';
myObj[a] = 'whatever';
alert(myObj.string1);
(alerts "whatever")
Ecu, if you do myObj.a, then it looks for the property named a of myObj.
If you do myObj[a] =b then it looks for the a.valueOf() property of myObj.
Oneliner:
obj = (function(attr, val){ var a = {}; a[attr]=val; return a; })('hash', 5);
Or:
attr = 'hash';
val = 5;
var obj = (obj={}, obj[attr]=val, obj);
Anything shorter?
You could just use this:
function createObject(propName, propValue){
this[propName] = propValue;
}
var myObj1 = new createObject('string1','string2');
Anything you pass as the first parameter will be the property name, and the second parameter is the property value.
You cannot use a variable to access a property via dot notation, instead use the array notation.
var obj= {
'name' : 'jroi'
};
var a = 'name';
alert(obj.a); //will not work
alert(obj[a]); //should work and alert jroi'
As $scope is an object, you can try with JavaScript by:
$scope['something'] = 'hey'
It is equal to:
$scope.something = 'hey'
I created a fiddle to test.
The following demonstrates an alternative approach for returning a key pair object using the form of (a, b). The first example uses the string 'key' as the property name, and 'val' as the value.
Example #1:
(function(o,a,b){return o[a]=b,o})({},'key','val');
Example: #2:
var obj = { foo: 'bar' };
(function(o,a,b){return o[a]=b,o})(obj,'key','val');
As shown in the second example, this can modify existing objects, too (if property is already defined in the object, value will be overwritten).
Result #1: { key: 'val' }
Result #2: { foo: 'bar', key: 'val' }
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";
The code below does what I want, but I would like to avoid eval. Is there a function in Javascript that looks up an object by its name as defined by in a string?
myobject = {"foo" : "bar"}
myname = "myobject";
eval(myname);
Some context: I am using this for an application in which a large number of nodes in the dom has a html5 data-object attribute, which is used in the handler function to connect back to the model.
Edit: myobject is neither global nor local, it is defined in one of the parent frames of the handler.
If variables are global then:
myobject = {"foo" : "bar"};
myname = "myobject";
window[myname].foo
DEMO
For local:
(function(){
myobject = {"foo" : "bar"};
myname = "myobject";
alert( this[myname].foo );
})();
DEMO
Local Variable Solution:
You could make all objects that you want to access with a string properties of another object. For example:
var objectHolder = {
myobject: {"foo" : "bar"},
myobject2: {"foo" : "bar"},
myobject3: {"foo" : "bar"}
};
And then access your desired object like this:
var desiredObject = objectHolder["myobject"];
Global Variable Solution:
You can access global variables using a string like this:
window["myobject"];
This question is pretty old, but since it's the top result on Google for the query "javascript get object from string", I thought I'd share a technique for longer object paths using dot notation.
Given the following:
var foo = { 'bar': { 'alpha': 'beta' } };
We can get the value of 'alpha' from a string like this:
var objPath = "bar.alpha";
var alphaVal = objPath.split('.')
.reduce(function (object, property) {
return object[property];
}, foo);
// alphaVal === "beta"
If it's global:
window.foo = { 'bar': { 'alpha': 'beta' } };
Just pass window as the initialValue for reduce:
var objPath = "foo.bar.alpha";
var alphaVal = objPath.split('.')
.reduce(function (object, property) {
return object[property];
}, window);
// alphaVal === "beta"
Basically we can use reduce to traverse object members by passing in the initial object as the initialValue.
MDN article for Array.prototype.reduce
since window is a global namespace, you could simply use
window[myname]
We use a fair bit of dotted notation variable structures. Needed a way to traverse them without erroring on undefined, and return value or undefined as the answer. Hope this helps.
function getValueOrUndefined(id) {
let parent = window;
if (id.indexOf(".") !== -1) {
let current = null;
let child = undefined;
let names = id.split(".");
for (let i = 0; i < names.length; i++) {
current = names[i];
child = parent[current];
if (child === undefined)
return child;
else
parent = child;
}
return child;
}
return parent[id];
}
Is it possible to create get/set function for undefined properties,
like in PHP __get() and __set() ?
You can access JavaScript object properties values using array access notation, you can also create a new property at any time using this notation or regular assignment notation.
var myObject = {};
myObject.Name = "Luis";
alert(myObject.Name);
alert(myObject["Name"]);
myObject["Name"] = "Dany";
alert(myObject.Name);
You can do
function ClassName(arg) {
var v = arg;
this.getter = function {
return v;
};
this.setter = function(val) {
v = val;
};
}
when you use it
var cn = new ClassName('a');
cn.setter('b');
alert(cn.getter()); /* alerts value 'b' */
Note that this uses the Constructor Invocation Pattern. By convention, you need to declare the function/class name with capital letter to indicate that this function/class need to be declared with the 'new' keyword.
Hope this helps
This question already has answers here:
Add a property to a JavaScript object using a variable as the name? [duplicate]
(14 answers)
Closed 7 years ago.
I want to add a new property to 'myObj', name it 'string1' and give it a value of 'string2', but when I do it it returns 'undefined:
var myObj = new Object;
var a = 'string1';
var b = 'string2';
myObj.a = b;
alert(myObj.string1); //Returns 'undefined'
alert(myObj.a); //Returns 'string2'
In other words: How do I create an object property and give it the name stored in the variable, but not the name of the variable itself?
There's the dot notation and the bracket notation
myObj[a] = b;
ES6 introduces computed property names, which allow you to do
var myObj = {[a]: b};
Dot notation and the properties are equivalent. So you would accomplish like so:
// const myObj = new Object();
const myObj = {};
const a = 'string1';
myObj[a] = 'whatever';
alert(myObj.string1);
(alerts "whatever")
Ecu, if you do myObj.a, then it looks for the property named a of myObj.
If you do myObj[a] =b then it looks for the a.valueOf() property of myObj.
Oneliner:
obj = (function(attr, val){ var a = {}; a[attr]=val; return a; })('hash', 5);
Or:
attr = 'hash';
val = 5;
var obj = (obj={}, obj[attr]=val, obj);
Anything shorter?
You could just use this:
function createObject(propName, propValue){
this[propName] = propValue;
}
var myObj1 = new createObject('string1','string2');
Anything you pass as the first parameter will be the property name, and the second parameter is the property value.
You cannot use a variable to access a property via dot notation, instead use the array notation.
var obj= {
'name' : 'jroi'
};
var a = 'name';
alert(obj.a); //will not work
alert(obj[a]); //should work and alert jroi'
As $scope is an object, you can try with JavaScript by:
$scope['something'] = 'hey'
It is equal to:
$scope.something = 'hey'
I created a fiddle to test.
The following demonstrates an alternative approach for returning a key pair object using the form of (a, b). The first example uses the string 'key' as the property name, and 'val' as the value.
Example #1:
(function(o,a,b){return o[a]=b,o})({},'key','val');
Example: #2:
var obj = { foo: 'bar' };
(function(o,a,b){return o[a]=b,o})(obj,'key','val');
As shown in the second example, this can modify existing objects, too (if property is already defined in the object, value will be overwritten).
Result #1: { key: 'val' }
Result #2: { foo: 'bar', key: 'val' }