How can a JavaScript object refer to values in itself?

JavascriptObject

Javascript Problem Overview


Lets say I have the following JavaScript:

var obj = {
 key1 : "it ",
 key2 : key1 + " works!"
};
alert(obj.key2);

This errors with "key1 is not defined". I have tried

this.key1
this[key1]
obj.key1
obj[key1]
this["key1"]
obj["key1"]

and they never seem to be defined.

How can I get key2 to refer to key1's value?

Javascript Solutions


Solution 1 - Javascript

Maybe you can think about removing the attribute to a function. I mean something like this:

var obj = {
  key1: "it ",
  key2: function() {
    return this.key1 + " works!";
  }
};

alert(obj.key2());

Solution 2 - Javascript

This can be achieved by using constructor function instead of literal

var o = new function() {
  this.foo = "it";
  this.bar = this.foo + " works"
}

alert(o.bar)

Solution 3 - Javascript

You can't refer to a property of an object before you have initialized that object; use an external variable.

var key1 = "it";
var obj = {
  key1 : key1,
  key2 : key1 + " works!"
};

Also, this is not a "JSON object"; it is a Javascript object. JSON is a method of representing an object with a string (which happens to be valid Javascript code).

Solution 4 - Javascript

One alternative would be to use a getter/setter methods.

For instance, if you only care about reading the calculated value:

var book  = {}

Object.defineProperties(book,{
	key1: { value: "it", enumerable: true },
	key2: {
        enumerable: true,
		get: function(){
			return this.key1 + " works!";
		}
	}
});

console.log(book.key2); //prints "it works!"

The above code, though, won't let you define another value for key2.

So, the things become a bit more complicated if you would like to also redefine the value of key2. It will always be a calculated value. Most likely that's what you want.

However, if you would like to be able to redefine the value of key2, then you will need a place to cache its value independently of the calculation.

Somewhat like this:

var book  = { _key2: " works!" }

Object.defineProperties(book,{
	key1: { value: "it", enumerable: true},
	_key2: { enumerable: false},
	key2: {
		enumerable: true,
		get: function(){
			return this.key1 + this._key2;
		},
		set: function(newValue){
			this._key2 = newValue;
		}
	}
});

console.log(book.key2); //it works!

book.key2 = " doesn't work!";
console.log(book.key2); //it doesn't work!

for(var key in book){
    //prints both key1 and key2, but not _key2
	console.log(key + ":" + book[key]); 
}

Another interesting alternative is to use a self-initializing object:

var obj = ({
  x: "it",
  init: function(){
    this.y = this.x + " works!";
    return this;
  }
}).init();

console.log(obj.y); //it works!

Solution 5 - Javascript

Because the statement defining obj hasn't finished, key1 doesn't exist yet. Consider this solution:

var obj = { key1: "it" };
obj.key2 = obj.key1 + ' ' + 'works!';
// obj.key2 is now 'it works!'

Solution 6 - Javascript

That's not a JSON object, that's a Javascript object created via object literal notation. (JSON is a textual notation for data exchange (more). If you're dealing with JavaScript source code, and not dealing with a string, you're not dealing with JSON.)

There's no way within the object initializer to refer to another key of the object being initialized, because there's no way to get a reference to the object being created until the initializer is finished. (There's no keyword akin to this or something for this situation.)

Solution 7 - Javascript

You can also reference the obj once you are inside the function instead of this.

var obj = {
    key1: "it",
    key2: function(){return obj.key1 + " works!"}
};
alert(obj.key2());

Solution 8 - Javascript

This is not JSON. JSON was designed to be simple; allowing arbitrary expressions is not simple.

In full JavaScript, I don't think you can do this directly. You cannot refer to this until the object called obj is fully constructed. So you need a workaround, that someone with more JavaScript-fu than I will provide.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionErin DrummondView Question on Stackoverflow
Solution 1 - JavascriptpencilCakeView Answer on Stackoverflow
Solution 2 - Javascriptuser187291View Answer on Stackoverflow
Solution 3 - JavascriptTgrView Answer on Stackoverflow
Solution 4 - JavascriptEdwin DalorzoView Answer on Stackoverflow
Solution 5 - JavascriptDelan AzabaniView Answer on Stackoverflow
Solution 6 - JavascriptT.J. CrowderView Answer on Stackoverflow
Solution 7 - JavascriptJasonView Answer on Stackoverflow
Solution 8 - JavascriptThomasView Answer on Stackoverflow