Christian
Christian

Reputation: 7429

Javascript Objects (dynamic attribute names)

if I have an object, something like this

var o = {
  test : 1
}

and I would like to have a second object, one of it's keys should be the value of o.test. Something like this:

var o2 = {
   o.test : "bla"
}

I know this is not possible, but is there a better (cleaner) way to do it as I do this now?

Currently what I dow is this:

var o2 = {};
o2[o.test] = "bla"

I guess there is a better way for this?

Upvotes: 3

Views: 336

Answers (3)

slebetman
slebetman

Reputation: 113974

This being javascript, there is almost always a workaround for doing what you want.

There is no syntax for doing what you want but you can certainly write a function to do it:

function make () {
    // Optional sanity check:
    if (arguments.length % 2) throw "Number of arguments should be even!";

    var obj = {};
    for (var name=0,val=1; name < arguments.length; name+=2,val+=2) {
        obj[arguments[name]] = arguments[val];
    }
    return obj;
}

Now you can write this:

var o2 = make(
    o.test,        'bla',
    'another_key', 'another_val'
);

Upvotes: 0

HMR
HMR

Reputation: 39310

Your Object properties can be any string

var o = {
  "whatever you want":1,
  "1":"numbers too"
}
o[2]="no numbers, convert to string"

console.log(o["whatever you want"]);//=1
console.log(o["1"]);//=numbers too
console.log(o[new String(2)]);//=no numbers, convert to string
// as James commented, you don't have to convert to string
// I usually do that as to not confuse the object with an array
console.log(o[2]);//=no numbers, convert to string

If all your "property names" are positive integers or 0 you could use an array:

var arr=new Array();//or var arr=[];
var b=22;
arr[10000]="hi";
arr[b]="value";
// normally you would do for(var i=0;len=arr.length;i<len;i++){...arr[i]
// but because there may be many empty spots it's quicker to do:
for(thing in arr){
  if(arr.hasOwnProperty(thing)){
    console.log(thing  + " is " + arr[thing]);
  }
}

Upvotes: 0

James Allardice
James Allardice

Reputation: 166021

I guess there is a better way for this?

Assuming I've understood your question correctly then no, not really. The way you've shown is the way to do it. There is no way to use a dynamic key inside the literal itself, so you have to declare it first and then assign the property separately:

var o2 = {};
o2[o.test] = "bla";

o2; // { 1: "bla" }

Update

The full details are given in the spec. Here's the grammar for object literal property identifiers:

PropertyName :
    IdentifierName
    StringLiteral
    NumericLiteral

The StringLiteral production is self-explanatory. Here's what the IdentifierName production does:

The production PropertyName : IdentifierName is evaluated as follows:

  1. Return the String value containing the same sequence of characters as the IdentifierName.

And for the NumericLiteral production:

The production PropertyName : NumericLiteral is evaluated as follows:

  1. Let nbr be the result of forming the value of the NumericLiteral.
  2. Return ToString(nbr).

You can see from this that it is not possible to use anything other than a string inside an object initialiser.

Upvotes: 7

Related Questions