Self invoking function inside an object literal [duplicate] - javascript

Is there any way to get something like the following to work in JavaScript?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
In the current form, this code obviously throws a reference error since this doesn't refer to foo. But is there any way to have values in an object literal's properties depend on other properties declared earlier?

Well, the only thing that I can tell you about are getter:
var foo = {
a: 5,
b: 6,
get c() {
return this.a + this.b;
}
}
console.log(foo.c) // 11
This is a syntactic extension introduced by the ECMAScript 5th Edition Specification, the syntax is supported by most modern browsers (including IE9).

You could do something like:
var foo = {
a: 5,
b: 6,
init: function() {
this.c = this.a + this.b;
return this;
}
}.init();
This would be some kind of one time initialization of the object.
Note that you are actually assigning the return value of init() to foo, therefore you have to return this.

The obvious, simple answer is missing, so for completeness:
But is there any way to have values in an object literal's properties depend on other properties declared earlier?
No. All of the solutions here defer it until after the object is created (in various ways) and then assign the third property. The simplest way is to just do this:
var foo = {
a: 5,
b: 6
};
foo.c = foo.a + foo.b;
All others are just more indirect ways to do the same thing. (Felix's is particularly clever, but requires creating and destroying a temporary function, adding complexity; and either leaves an extra property on the object or [if you delete that property] impacts the performance of subsequent property accesses on that object.)
If you need it to all be within one expression, you can do that without the temporary property:
var foo = function(o) {
o.c = o.a + o.b;
return o;
}({a: 5, b: 6});
Or of course, if you need to do this more than once:
function buildFoo(a, b) {
var o = {a: a, b: b};
o.c = o.a + o.b;
return o;
}
then where you need to use it:
var foo = buildFoo(5, 6);

Simply instantiate an anonymous function:
var foo = new function () {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
};

Now in ES6 you can create lazy cached properties. On first use the property evaluates once to become a normal static property. Result: The second time the math function overhead is skipped.
The magic is in the getter.
const foo = {
a: 5,
b: 6,
get c() {
delete this.c;
return this.c = this.a + this.b
}
};
In the arrow getter this picks up the surrounding lexical scope.
foo // {a: 5, b: 6}
foo.c // 11
foo // {a: 5, b: 6 , c: 11}

Some closure should deal with this;
var foo = function() {
var a = 5;
var b = 6;
var c = a + b;
return {
a: a,
b: b,
c: c
}
}();
All the variables declared within foo are private to foo, as you would expect with any function declaration and because they are all in scope, they all have access to each other without needing to refer to this, just as you would expect with a function. The difference is that this function returns an object that exposes the private variables and assigns that object to foo. In the end, you return just the interface you want to expose as an object with the return {} statement.
The function is then executed at the end with the () which causes the entire foo object to be evaluated, all the variables within instantiated and the return object added as properties of foo().

You could do it like this
var a, b
var foo = {
a: a = 5,
b: b = 6,
c: a + b
}
That method has proven useful to me when I had to refer to the object that a function was originally declared on. The following is a minimal example of how I used it:
function createMyObject() {
var count = 0, self
return {
a: self = {
log: function() {
console.log(count++)
return self
}
}
}
}
By defining self as the object that contains the print function you allow the function to refer to that object. This means you will not have to 'bind' the print function to an object if you need to pass it somewhere else.
If you would, instead, use this as illustrated below
function createMyObject() {
var count = 0
return {
a: {
log: function() {
console.log(count++)
return this
}
}
}
}
Then the following code will log 0, 1, 2 and then give an error
var o = createMyObject()
var log = o.a.log
o.a.log().log() // this refers to the o.a object so the chaining works
log().log() // this refers to the window object so the chaining fails!
By using the self method you guarantee that print will always return the same object regardless of the context in which the function is ran. The code above will run just fine and log 0, 1, 2 and 3 when using the self version of createMyObject().

For completion, in ES6 we've got classes (supported at the time of writing this only by latest browsers, but available in Babel, TypeScript and other transpilers)
class Foo {
constructor(){
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
}
}
const foo = new Foo();

just for the sake of thought - place object's properties out of a timeline:
var foo = {
a: function(){return 5}(),
b: function(){return 6}(),
c: function(){return this.a + this.b}
}
console.log(foo.c())
there are better answers above too. This is how I modified example code you questioned with.
UPDATE:
var foo = {
get a(){return 5},
get b(){return 6},
get c(){return this.a + this.b}
}
// console.log(foo.c);

You can do it using the module pattern. Just like:
var foo = function() {
var that = {};
that.a = 7;
that.b = 6;
that.c = function() {
return that.a + that.b;
}
return that;
};
var fooObject = foo();
fooObject.c(); //13
With this pattern you can instantiate several foo objects according to your need.
http://jsfiddle.net/jPNxY/1/

There are several ways to accomplish this; this is what I would use:
function Obj() {
this.a = 5;
this.b = this.a + 1;
// return this; // commented out because this happens automatically
}
var o = new Obj();
o.b; // === 6

The get property works great, and you can also use a binded closure for "expensive" functions that should only run once (this only works with var, not with const or let)
var info = {
address: (function() {
return databaseLookup(this.id)
}).bind(info)(),
get fullName() {
console.log('computing fullName...')
return `${this.first} ${this.last}`
},
id: '555-22-9999',
first: 'First',
last: 'Last',
}
function databaseLookup() {
console.log('fetching address from remote server (runs once)...')
return Promise.resolve(`22 Main St, City, Country`)
}
// test
(async () => {
console.log(info.fullName)
console.log(info.fullName)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
})()

Creating new function on your object literal and invoking a constructor seems a radical departure from the original problem, and it's unnecessary.
You cannot reference a sibling property during object literal initialization.
var x = { a: 1, b: 2, c: a + b } // not defined
var y = { a: 1, b: 2, c: y.a + y.b } // not defined
The simplest solution for computed properties follows (no heap, no functions, no constructor):
var x = { a: 1, b: 2 };
x.c = x.a + x.b; // apply computed property

I use the following code as alternative, and it works. And the variable can be array too. (# Fausto R.)
var foo = {
a: 5,
b: 6,
c: function() {
return this.a + this.b;
},
d: [10,20,30],
e: function(x) {
this.d.push(x);
return this.d;
}
};
foo.c(); // 11
foo.e(40); // foo.d = [10,20,30,40]

Just for everyone's amusement:
var foo = ( (This={
a: 5,
b: 6, })=>({...This,
c: This.a + This.b }))(
);
console.log(foo);

The other answers posted here are better but here's an alternative that:
Sets the value at initialization (not a getter, or derived, etc)
Doesn't require any type of init() or code outside of the object literal
Is an object literal and not a factory function or other object creation mechanic.
Shouldn't have any performance impact (except at initialization)
Self-executing anonymous functions and window storage
var foo = {
bar:(function(){
window.temp = "qwert";
return window.temp;
})(),
baz: window.temp
};
The order is guaranteed (bar before baz).
It pollutes window of course, but I can't imagine someone writing a script that requires window.temp to be persistent. Maybe tempMyApp if you're paranoid.
It's also ugly but occasionally useful. An example is when you are using an API with rigid initialization conditions and don't feel like refactoring so the scoping is correct.
And it's dry, of course.

The key to all this is SCOPE.
You need to encapsulate the "parent" (parent object) of the property you want to define as it's own instantiated object, and then you can make references to sibling properties using the key word this
It's very, very important to remember that if you refer to this without first so doing, then this will refer to the outer scope... which will be the window object.
var x = 9 //this is really window.x
var bar = {
x: 1,
y: 2,
foo: new function(){
this.a = 5, //assign value
this.b = 6,
this.c = this.a + this.b; // 11
},
z: this.x // 9 (not 1 as you might expect, b/c *this* refers `window` object)
};

if your object is written as a function which returns an object, AND you use ES6 object-attribute 'methods', then it's possible:
const module = (state) => ({
a: 1,
oneThing() {
state.b = state.b + this.a
},
anotherThing() {
this.oneThing();
state.c = state.b + this.a
},
});
const store = {b: 10};
const root = module(store);
root.oneThing();
console.log(store);
root.anotherThing();
console.log(store);
console.log(root, Object.keys(root), root.prototype);

Here's a neat ES6 way:
var foo = (o => ({
...o,
c: o.a + o.b
}))({
a: 5,
b: 6
});
console.log(foo);
I use it to do something like this:
const constants = Object.freeze(
(_ => ({
..._,
flag_data: {
[_.a_flag]: 'foo',
[_.b_flag]: 'bar',
[_.c_flag]: 'oof'
}
}))({
a_flag: 5,
b_flag: 6,
c_flag: 7,
})
);
console.log(constants.flag_data[constants.b_flag]);

How about this solution this will work with nested objects with array as well
Object.prototype.assignOwnProVal
= function (to,from){
function compose(obj,string){
var parts = string.split('.');
var newObj = obj[parts[0]];
if(parts[1]){
parts.splice(0,1);
var newString = parts.join('.');
return compose(newObj,newString);
}
return newObj;
}
this[to] = compose(this,from);
}
var obj = { name : 'Gaurav', temp :
{id : [10,20], city:
{street:'Brunswick'}} }
obj.assignOwnProVal('street','temp.city.street');
obj.assignOwnProVal('myid','temp.id.1');

Throwing in an option since I didn't see this exact scenario covered. If you don't want c updated when a or b update, then an ES6 IIFE works well.
var foo = ((a,b) => ({
a,
b,
c: a + b
}))(a,b);
For my needs, I have an object that relates to an array which will end up being used in a loop, so I only want to calculate some common setup once, so this is what I have:
let processingState = ((indexOfSelectedTier) => ({
selectedTier,
indexOfSelectedTier,
hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier)
.some(t => pendingSelectedFiltersState[t.name]),
}))(tiers.indexOf(selectedTier));
Since I need to set a property for indexOfSelectedTier and I need to use that value when setting the hasUpperTierSelection property, I calculate that value first and pass it in as a param to the IIFE

Here is an example of behavior of 'this' in the object.
this.prop = 'external';
global.prop = 'global.prop';
const that = this;
const a = {
prop: 'internal',
prop1: this.prop, //external
log() {
return this.prop //internal
},
log1: () => {
return this.prop //external
},
log2: () => {
return function () {
return this.prop; //'global.prop' in node; 'external' in chrome
}()
},
log3: function () {
return (() => {
return this.prop; //internal
})()
},
}

I think following is best code for maintanability even though it's not in object literal syntax:
var foo = function() {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
return this;
}.call({});
This creates a new empty object with {} and then uses the anonymous function to set its properties (executed with call()). I think the only bad part is the need for return this which feels like one extra line of code. Unfortunately, I cannot figure out any nicer way to move the reference to newly created anonymous object to foo.
I think this is better than syntax var foo = new function() {...} because this one doesn't create one extra level in the prototype chain as explained by #Bergi in the comments in one of the existing answers.
However, if this is truly literal without any other logic but one addition, it would make more sense to just write
const foo = {
a:5,
b:6,
c:11, // sum of a + b
};
because there's no need to calculate that sum during runtime or even compile time.

Ok I came up with another solution. Here I want to initialize an object representing the amount of milliseconds for each unit of time.
It turns out enum in typescript can not be used in my case, so I declared multiple variables that I assign to an object as follow:
const SECOND = 1000
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
const WEEK = 7 * DAY
export const TimeInMS = {
SECOND,
MINUTE,
HOUR,
DAY,
WEEK
}
The drawbacks of this method are:
variables are defined as constants, even if we dont need them. Thus it needs useless memory.
each value of the object must be declared as standalone variable

Alternative syntax with pretty good maintanability:
let a = 5;
let b = 6;
let foo = {
a,
b,
c: a+b,
};
This works because JavaScript will use the variable name as the property name for the newly created object if you don't specify the name explicitly. For a short array like this, I'd personally go with single line syntax with return if this were inside a function:
let a = 5;
let b = 6;
return { a, b, c:a+b };

Note: This solution uses Typescript (you can use the vanilla JS which TS compiles to if needed)
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
// this method is just to check/test this solution
check(){
console.log(this.def.qwe);
}
}
// these two lines are just to check
let instance = new asd();
instance.check();
Here were using class expressions to get the nested object literal interface we'd want. This is the next best thing IMHO to being able to reference the properties of an object during creation.
Main thing to note is while using this solution, you have exact same interface as you'd have had from an object literal. And the syntax is pretty close to an object literal itself (vs using a function, etc).
Compare the following
Solution I've proposed
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
Solution if object literals would've sufficed
var asd = {
def : {
ads:'asd',
qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
}
}
Another example
Here in this class, you can combine multiple relative path among themselves, which is not possible with an object literal.
class CONSTANT {
static readonly PATH = new class {
/** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
*
*/
private readonly RELATIVE = new class {
readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
};
}
}

Other approach would be to declare the object first before assigning properties into it:
const foo = {};
foo.a = 5;
foo.b = 6;
foo.c = foo.a + foo.b; // Does work
foo.getSum = () => foo.a + foo.b + foo.c; // foo.getSum() === 22
With that, you can use the object variable name to access the already assigned values.
Best for config.js file.

If you want to use native JS, the other answers provide good solutions.
But if you're willing to write self-referencing objects like:
{
a: ...,
b: "${this.a + this.a}",
}
I wrote an npm library called self-referenced-object that supports that syntax and returns a native object.

Two lazy solutions
There are already excellent answers here and I'm no expert on this, but I am an expert in being lazy and to my expert eye these answers don't seem lazy enough.
First: return object from anonymous function
A very slight variation from T.J. Crowder, Henry Wrightson and Rafael Rocha answers:
var foo = (() => {
// Paste in your original object
const foo = {
a: 5,
b: 6,
};
// Use their properties
foo.c = foo.a + foo.b;
// Do whatever else you want
// Finally, return object
return foo;
})();
console.log(foo);
The slight advantage here is just pasting your original object as it was, without worrying about arguments etc. (IMHO the wrapper function becomes quite transparent this way).
Second: using setTimeout
This here may work, if you don't need foo.c right away:
var foo = {
a: 5,
b: 6,
c: setTimeout(() => foo.c = foo.a + foo.b, 0)
};
// Though, at first, foo.c will be the integer returned by setTimeout
console.log(foo);
// But if this isn't an issue, the value will be updated when time comes in the event loop
setTimeout( () => console.log(foo), 0);

var x = {
a: (window.secreta = 5),
b: (window.secretb = 6),
c: window.secreta + window.secretb
};
This is almost identical to #slicedtoad's answer, but doesn't use a function.

Related

Calling outside function inside an object JS [duplicate]

Is there any way to get something like the following to work in JavaScript?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
In the current form, this code obviously throws a reference error since this doesn't refer to foo. But is there any way to have values in an object literal's properties depend on other properties declared earlier?
Well, the only thing that I can tell you about are getter:
var foo = {
a: 5,
b: 6,
get c() {
return this.a + this.b;
}
}
console.log(foo.c) // 11
This is a syntactic extension introduced by the ECMAScript 5th Edition Specification, the syntax is supported by most modern browsers (including IE9).
You could do something like:
var foo = {
a: 5,
b: 6,
init: function() {
this.c = this.a + this.b;
return this;
}
}.init();
This would be some kind of one time initialization of the object.
Note that you are actually assigning the return value of init() to foo, therefore you have to return this.
The obvious, simple answer is missing, so for completeness:
But is there any way to have values in an object literal's properties depend on other properties declared earlier?
No. All of the solutions here defer it until after the object is created (in various ways) and then assign the third property. The simplest way is to just do this:
var foo = {
a: 5,
b: 6
};
foo.c = foo.a + foo.b;
All others are just more indirect ways to do the same thing. (Felix's is particularly clever, but requires creating and destroying a temporary function, adding complexity; and either leaves an extra property on the object or [if you delete that property] impacts the performance of subsequent property accesses on that object.)
If you need it to all be within one expression, you can do that without the temporary property:
var foo = function(o) {
o.c = o.a + o.b;
return o;
}({a: 5, b: 6});
Or of course, if you need to do this more than once:
function buildFoo(a, b) {
var o = {a: a, b: b};
o.c = o.a + o.b;
return o;
}
then where you need to use it:
var foo = buildFoo(5, 6);
Simply instantiate an anonymous function:
var foo = new function () {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
};
Now in ES6 you can create lazy cached properties. On first use the property evaluates once to become a normal static property. Result: The second time the math function overhead is skipped.
The magic is in the getter.
const foo = {
a: 5,
b: 6,
get c() {
delete this.c;
return this.c = this.a + this.b
}
};
In the arrow getter this picks up the surrounding lexical scope.
foo // {a: 5, b: 6}
foo.c // 11
foo // {a: 5, b: 6 , c: 11}
Some closure should deal with this;
var foo = function() {
var a = 5;
var b = 6;
var c = a + b;
return {
a: a,
b: b,
c: c
}
}();
All the variables declared within foo are private to foo, as you would expect with any function declaration and because they are all in scope, they all have access to each other without needing to refer to this, just as you would expect with a function. The difference is that this function returns an object that exposes the private variables and assigns that object to foo. In the end, you return just the interface you want to expose as an object with the return {} statement.
The function is then executed at the end with the () which causes the entire foo object to be evaluated, all the variables within instantiated and the return object added as properties of foo().
You could do it like this
var a, b
var foo = {
a: a = 5,
b: b = 6,
c: a + b
}
That method has proven useful to me when I had to refer to the object that a function was originally declared on. The following is a minimal example of how I used it:
function createMyObject() {
var count = 0, self
return {
a: self = {
log: function() {
console.log(count++)
return self
}
}
}
}
By defining self as the object that contains the print function you allow the function to refer to that object. This means you will not have to 'bind' the print function to an object if you need to pass it somewhere else.
If you would, instead, use this as illustrated below
function createMyObject() {
var count = 0
return {
a: {
log: function() {
console.log(count++)
return this
}
}
}
}
Then the following code will log 0, 1, 2 and then give an error
var o = createMyObject()
var log = o.a.log
o.a.log().log() // this refers to the o.a object so the chaining works
log().log() // this refers to the window object so the chaining fails!
By using the self method you guarantee that print will always return the same object regardless of the context in which the function is ran. The code above will run just fine and log 0, 1, 2 and 3 when using the self version of createMyObject().
For completion, in ES6 we've got classes (supported at the time of writing this only by latest browsers, but available in Babel, TypeScript and other transpilers)
class Foo {
constructor(){
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
}
}
const foo = new Foo();
just for the sake of thought - place object's properties out of a timeline:
var foo = {
a: function(){return 5}(),
b: function(){return 6}(),
c: function(){return this.a + this.b}
}
console.log(foo.c())
there are better answers above too. This is how I modified example code you questioned with.
UPDATE:
var foo = {
get a(){return 5},
get b(){return 6},
get c(){return this.a + this.b}
}
// console.log(foo.c);
You can do it using the module pattern. Just like:
var foo = function() {
var that = {};
that.a = 7;
that.b = 6;
that.c = function() {
return that.a + that.b;
}
return that;
};
var fooObject = foo();
fooObject.c(); //13
With this pattern you can instantiate several foo objects according to your need.
http://jsfiddle.net/jPNxY/1/
There are several ways to accomplish this; this is what I would use:
function Obj() {
this.a = 5;
this.b = this.a + 1;
// return this; // commented out because this happens automatically
}
var o = new Obj();
o.b; // === 6
The get property works great, and you can also use a binded closure for "expensive" functions that should only run once (this only works with var, not with const or let)
var info = {
address: (function() {
return databaseLookup(this.id)
}).bind(info)(),
get fullName() {
console.log('computing fullName...')
return `${this.first} ${this.last}`
},
id: '555-22-9999',
first: 'First',
last: 'Last',
}
function databaseLookup() {
console.log('fetching address from remote server (runs once)...')
return Promise.resolve(`22 Main St, City, Country`)
}
// test
(async () => {
console.log(info.fullName)
console.log(info.fullName)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
})()
Creating new function on your object literal and invoking a constructor seems a radical departure from the original problem, and it's unnecessary.
You cannot reference a sibling property during object literal initialization.
var x = { a: 1, b: 2, c: a + b } // not defined
var y = { a: 1, b: 2, c: y.a + y.b } // not defined
The simplest solution for computed properties follows (no heap, no functions, no constructor):
var x = { a: 1, b: 2 };
x.c = x.a + x.b; // apply computed property
I use the following code as alternative, and it works. And the variable can be array too. (# Fausto R.)
var foo = {
a: 5,
b: 6,
c: function() {
return this.a + this.b;
},
d: [10,20,30],
e: function(x) {
this.d.push(x);
return this.d;
}
};
foo.c(); // 11
foo.e(40); // foo.d = [10,20,30,40]
Just for everyone's amusement:
var foo = ( (This={
a: 5,
b: 6, })=>({...This,
c: This.a + This.b }))(
);
console.log(foo);
The other answers posted here are better but here's an alternative that:
Sets the value at initialization (not a getter, or derived, etc)
Doesn't require any type of init() or code outside of the object literal
Is an object literal and not a factory function or other object creation mechanic.
Shouldn't have any performance impact (except at initialization)
Self-executing anonymous functions and window storage
var foo = {
bar:(function(){
window.temp = "qwert";
return window.temp;
})(),
baz: window.temp
};
The order is guaranteed (bar before baz).
It pollutes window of course, but I can't imagine someone writing a script that requires window.temp to be persistent. Maybe tempMyApp if you're paranoid.
It's also ugly but occasionally useful. An example is when you are using an API with rigid initialization conditions and don't feel like refactoring so the scoping is correct.
And it's dry, of course.
The key to all this is SCOPE.
You need to encapsulate the "parent" (parent object) of the property you want to define as it's own instantiated object, and then you can make references to sibling properties using the key word this
It's very, very important to remember that if you refer to this without first so doing, then this will refer to the outer scope... which will be the window object.
var x = 9 //this is really window.x
var bar = {
x: 1,
y: 2,
foo: new function(){
this.a = 5, //assign value
this.b = 6,
this.c = this.a + this.b; // 11
},
z: this.x // 9 (not 1 as you might expect, b/c *this* refers `window` object)
};
if your object is written as a function which returns an object, AND you use ES6 object-attribute 'methods', then it's possible:
const module = (state) => ({
a: 1,
oneThing() {
state.b = state.b + this.a
},
anotherThing() {
this.oneThing();
state.c = state.b + this.a
},
});
const store = {b: 10};
const root = module(store);
root.oneThing();
console.log(store);
root.anotherThing();
console.log(store);
console.log(root, Object.keys(root), root.prototype);
Here's a neat ES6 way:
var foo = (o => ({
...o,
c: o.a + o.b
}))({
a: 5,
b: 6
});
console.log(foo);
I use it to do something like this:
const constants = Object.freeze(
(_ => ({
..._,
flag_data: {
[_.a_flag]: 'foo',
[_.b_flag]: 'bar',
[_.c_flag]: 'oof'
}
}))({
a_flag: 5,
b_flag: 6,
c_flag: 7,
})
);
console.log(constants.flag_data[constants.b_flag]);
How about this solution this will work with nested objects with array as well
Object.prototype.assignOwnProVal
= function (to,from){
function compose(obj,string){
var parts = string.split('.');
var newObj = obj[parts[0]];
if(parts[1]){
parts.splice(0,1);
var newString = parts.join('.');
return compose(newObj,newString);
}
return newObj;
}
this[to] = compose(this,from);
}
var obj = { name : 'Gaurav', temp :
{id : [10,20], city:
{street:'Brunswick'}} }
obj.assignOwnProVal('street','temp.city.street');
obj.assignOwnProVal('myid','temp.id.1');
Throwing in an option since I didn't see this exact scenario covered. If you don't want c updated when a or b update, then an ES6 IIFE works well.
var foo = ((a,b) => ({
a,
b,
c: a + b
}))(a,b);
For my needs, I have an object that relates to an array which will end up being used in a loop, so I only want to calculate some common setup once, so this is what I have:
let processingState = ((indexOfSelectedTier) => ({
selectedTier,
indexOfSelectedTier,
hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier)
.some(t => pendingSelectedFiltersState[t.name]),
}))(tiers.indexOf(selectedTier));
Since I need to set a property for indexOfSelectedTier and I need to use that value when setting the hasUpperTierSelection property, I calculate that value first and pass it in as a param to the IIFE
Here is an example of behavior of 'this' in the object.
this.prop = 'external';
global.prop = 'global.prop';
const that = this;
const a = {
prop: 'internal',
prop1: this.prop, //external
log() {
return this.prop //internal
},
log1: () => {
return this.prop //external
},
log2: () => {
return function () {
return this.prop; //'global.prop' in node; 'external' in chrome
}()
},
log3: function () {
return (() => {
return this.prop; //internal
})()
},
}
I think following is best code for maintanability even though it's not in object literal syntax:
var foo = function() {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
return this;
}.call({});
This creates a new empty object with {} and then uses the anonymous function to set its properties (executed with call()). I think the only bad part is the need for return this which feels like one extra line of code. Unfortunately, I cannot figure out any nicer way to move the reference to newly created anonymous object to foo.
I think this is better than syntax var foo = new function() {...} because this one doesn't create one extra level in the prototype chain as explained by #Bergi in the comments in one of the existing answers.
However, if this is truly literal without any other logic but one addition, it would make more sense to just write
const foo = {
a:5,
b:6,
c:11, // sum of a + b
};
because there's no need to calculate that sum during runtime or even compile time.
Ok I came up with another solution. Here I want to initialize an object representing the amount of milliseconds for each unit of time.
It turns out enum in typescript can not be used in my case, so I declared multiple variables that I assign to an object as follow:
const SECOND = 1000
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
const WEEK = 7 * DAY
export const TimeInMS = {
SECOND,
MINUTE,
HOUR,
DAY,
WEEK
}
The drawbacks of this method are:
variables are defined as constants, even if we dont need them. Thus it needs useless memory.
each value of the object must be declared as standalone variable
Alternative syntax with pretty good maintanability:
let a = 5;
let b = 6;
let foo = {
a,
b,
c: a+b,
};
This works because JavaScript will use the variable name as the property name for the newly created object if you don't specify the name explicitly. For a short array like this, I'd personally go with single line syntax with return if this were inside a function:
let a = 5;
let b = 6;
return { a, b, c:a+b };
Note: This solution uses Typescript (you can use the vanilla JS which TS compiles to if needed)
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
// this method is just to check/test this solution
check(){
console.log(this.def.qwe);
}
}
// these two lines are just to check
let instance = new asd();
instance.check();
Here were using class expressions to get the nested object literal interface we'd want. This is the next best thing IMHO to being able to reference the properties of an object during creation.
Main thing to note is while using this solution, you have exact same interface as you'd have had from an object literal. And the syntax is pretty close to an object literal itself (vs using a function, etc).
Compare the following
Solution I've proposed
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
Solution if object literals would've sufficed
var asd = {
def : {
ads:'asd',
qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
}
}
Another example
Here in this class, you can combine multiple relative path among themselves, which is not possible with an object literal.
class CONSTANT {
static readonly PATH = new class {
/** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
*
*/
private readonly RELATIVE = new class {
readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
};
}
}
Other approach would be to declare the object first before assigning properties into it:
const foo = {};
foo.a = 5;
foo.b = 6;
foo.c = foo.a + foo.b; // Does work
foo.getSum = () => foo.a + foo.b + foo.c; // foo.getSum() === 22
With that, you can use the object variable name to access the already assigned values.
Best for config.js file.
If you want to use native JS, the other answers provide good solutions.
But if you're willing to write self-referencing objects like:
{
a: ...,
b: "${this.a + this.a}",
}
I wrote an npm library called self-referenced-object that supports that syntax and returns a native object.
Two lazy solutions
There are already excellent answers here and I'm no expert on this, but I am an expert in being lazy and to my expert eye these answers don't seem lazy enough.
First: return object from anonymous function
A very slight variation from T.J. Crowder, Henry Wrightson and Rafael Rocha answers:
var foo = (() => {
// Paste in your original object
const foo = {
a: 5,
b: 6,
};
// Use their properties
foo.c = foo.a + foo.b;
// Do whatever else you want
// Finally, return object
return foo;
})();
console.log(foo);
The slight advantage here is just pasting your original object as it was, without worrying about arguments etc. (IMHO the wrapper function becomes quite transparent this way).
Second: using setTimeout
This here may work, if you don't need foo.c right away:
var foo = {
a: 5,
b: 6,
c: setTimeout(() => foo.c = foo.a + foo.b, 0)
};
// Though, at first, foo.c will be the integer returned by setTimeout
console.log(foo);
// But if this isn't an issue, the value will be updated when time comes in the event loop
setTimeout( () => console.log(foo), 0);
var x = {
a: (window.secreta = 5),
b: (window.secretb = 6),
c: window.secreta + window.secretb
};
This is almost identical to #slicedtoad's answer, but doesn't use a function.

Callback in closure function [duplicate]

Is there any way to get something like the following to work in JavaScript?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
In the current form, this code obviously throws a reference error since this doesn't refer to foo. But is there any way to have values in an object literal's properties depend on other properties declared earlier?
Well, the only thing that I can tell you about are getter:
var foo = {
a: 5,
b: 6,
get c() {
return this.a + this.b;
}
}
console.log(foo.c) // 11
This is a syntactic extension introduced by the ECMAScript 5th Edition Specification, the syntax is supported by most modern browsers (including IE9).
You could do something like:
var foo = {
a: 5,
b: 6,
init: function() {
this.c = this.a + this.b;
return this;
}
}.init();
This would be some kind of one time initialization of the object.
Note that you are actually assigning the return value of init() to foo, therefore you have to return this.
The obvious, simple answer is missing, so for completeness:
But is there any way to have values in an object literal's properties depend on other properties declared earlier?
No. All of the solutions here defer it until after the object is created (in various ways) and then assign the third property. The simplest way is to just do this:
var foo = {
a: 5,
b: 6
};
foo.c = foo.a + foo.b;
All others are just more indirect ways to do the same thing. (Felix's is particularly clever, but requires creating and destroying a temporary function, adding complexity; and either leaves an extra property on the object or [if you delete that property] impacts the performance of subsequent property accesses on that object.)
If you need it to all be within one expression, you can do that without the temporary property:
var foo = function(o) {
o.c = o.a + o.b;
return o;
}({a: 5, b: 6});
Or of course, if you need to do this more than once:
function buildFoo(a, b) {
var o = {a: a, b: b};
o.c = o.a + o.b;
return o;
}
then where you need to use it:
var foo = buildFoo(5, 6);
Simply instantiate an anonymous function:
var foo = new function () {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
};
Now in ES6 you can create lazy cached properties. On first use the property evaluates once to become a normal static property. Result: The second time the math function overhead is skipped.
The magic is in the getter.
const foo = {
a: 5,
b: 6,
get c() {
delete this.c;
return this.c = this.a + this.b
}
};
In the arrow getter this picks up the surrounding lexical scope.
foo // {a: 5, b: 6}
foo.c // 11
foo // {a: 5, b: 6 , c: 11}
Some closure should deal with this;
var foo = function() {
var a = 5;
var b = 6;
var c = a + b;
return {
a: a,
b: b,
c: c
}
}();
All the variables declared within foo are private to foo, as you would expect with any function declaration and because they are all in scope, they all have access to each other without needing to refer to this, just as you would expect with a function. The difference is that this function returns an object that exposes the private variables and assigns that object to foo. In the end, you return just the interface you want to expose as an object with the return {} statement.
The function is then executed at the end with the () which causes the entire foo object to be evaluated, all the variables within instantiated and the return object added as properties of foo().
You could do it like this
var a, b
var foo = {
a: a = 5,
b: b = 6,
c: a + b
}
That method has proven useful to me when I had to refer to the object that a function was originally declared on. The following is a minimal example of how I used it:
function createMyObject() {
var count = 0, self
return {
a: self = {
log: function() {
console.log(count++)
return self
}
}
}
}
By defining self as the object that contains the print function you allow the function to refer to that object. This means you will not have to 'bind' the print function to an object if you need to pass it somewhere else.
If you would, instead, use this as illustrated below
function createMyObject() {
var count = 0
return {
a: {
log: function() {
console.log(count++)
return this
}
}
}
}
Then the following code will log 0, 1, 2 and then give an error
var o = createMyObject()
var log = o.a.log
o.a.log().log() // this refers to the o.a object so the chaining works
log().log() // this refers to the window object so the chaining fails!
By using the self method you guarantee that print will always return the same object regardless of the context in which the function is ran. The code above will run just fine and log 0, 1, 2 and 3 when using the self version of createMyObject().
For completion, in ES6 we've got classes (supported at the time of writing this only by latest browsers, but available in Babel, TypeScript and other transpilers)
class Foo {
constructor(){
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
}
}
const foo = new Foo();
just for the sake of thought - place object's properties out of a timeline:
var foo = {
a: function(){return 5}(),
b: function(){return 6}(),
c: function(){return this.a + this.b}
}
console.log(foo.c())
there are better answers above too. This is how I modified example code you questioned with.
UPDATE:
var foo = {
get a(){return 5},
get b(){return 6},
get c(){return this.a + this.b}
}
// console.log(foo.c);
You can do it using the module pattern. Just like:
var foo = function() {
var that = {};
that.a = 7;
that.b = 6;
that.c = function() {
return that.a + that.b;
}
return that;
};
var fooObject = foo();
fooObject.c(); //13
With this pattern you can instantiate several foo objects according to your need.
http://jsfiddle.net/jPNxY/1/
There are several ways to accomplish this; this is what I would use:
function Obj() {
this.a = 5;
this.b = this.a + 1;
// return this; // commented out because this happens automatically
}
var o = new Obj();
o.b; // === 6
The get property works great, and you can also use a binded closure for "expensive" functions that should only run once (this only works with var, not with const or let)
var info = {
address: (function() {
return databaseLookup(this.id)
}).bind(info)(),
get fullName() {
console.log('computing fullName...')
return `${this.first} ${this.last}`
},
id: '555-22-9999',
first: 'First',
last: 'Last',
}
function databaseLookup() {
console.log('fetching address from remote server (runs once)...')
return Promise.resolve(`22 Main St, City, Country`)
}
// test
(async () => {
console.log(info.fullName)
console.log(info.fullName)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
})()
Creating new function on your object literal and invoking a constructor seems a radical departure from the original problem, and it's unnecessary.
You cannot reference a sibling property during object literal initialization.
var x = { a: 1, b: 2, c: a + b } // not defined
var y = { a: 1, b: 2, c: y.a + y.b } // not defined
The simplest solution for computed properties follows (no heap, no functions, no constructor):
var x = { a: 1, b: 2 };
x.c = x.a + x.b; // apply computed property
I use the following code as alternative, and it works. And the variable can be array too. (# Fausto R.)
var foo = {
a: 5,
b: 6,
c: function() {
return this.a + this.b;
},
d: [10,20,30],
e: function(x) {
this.d.push(x);
return this.d;
}
};
foo.c(); // 11
foo.e(40); // foo.d = [10,20,30,40]
Just for everyone's amusement:
var foo = ( (This={
a: 5,
b: 6, })=>({...This,
c: This.a + This.b }))(
);
console.log(foo);
The other answers posted here are better but here's an alternative that:
Sets the value at initialization (not a getter, or derived, etc)
Doesn't require any type of init() or code outside of the object literal
Is an object literal and not a factory function or other object creation mechanic.
Shouldn't have any performance impact (except at initialization)
Self-executing anonymous functions and window storage
var foo = {
bar:(function(){
window.temp = "qwert";
return window.temp;
})(),
baz: window.temp
};
The order is guaranteed (bar before baz).
It pollutes window of course, but I can't imagine someone writing a script that requires window.temp to be persistent. Maybe tempMyApp if you're paranoid.
It's also ugly but occasionally useful. An example is when you are using an API with rigid initialization conditions and don't feel like refactoring so the scoping is correct.
And it's dry, of course.
The key to all this is SCOPE.
You need to encapsulate the "parent" (parent object) of the property you want to define as it's own instantiated object, and then you can make references to sibling properties using the key word this
It's very, very important to remember that if you refer to this without first so doing, then this will refer to the outer scope... which will be the window object.
var x = 9 //this is really window.x
var bar = {
x: 1,
y: 2,
foo: new function(){
this.a = 5, //assign value
this.b = 6,
this.c = this.a + this.b; // 11
},
z: this.x // 9 (not 1 as you might expect, b/c *this* refers `window` object)
};
if your object is written as a function which returns an object, AND you use ES6 object-attribute 'methods', then it's possible:
const module = (state) => ({
a: 1,
oneThing() {
state.b = state.b + this.a
},
anotherThing() {
this.oneThing();
state.c = state.b + this.a
},
});
const store = {b: 10};
const root = module(store);
root.oneThing();
console.log(store);
root.anotherThing();
console.log(store);
console.log(root, Object.keys(root), root.prototype);
Here's a neat ES6 way:
var foo = (o => ({
...o,
c: o.a + o.b
}))({
a: 5,
b: 6
});
console.log(foo);
I use it to do something like this:
const constants = Object.freeze(
(_ => ({
..._,
flag_data: {
[_.a_flag]: 'foo',
[_.b_flag]: 'bar',
[_.c_flag]: 'oof'
}
}))({
a_flag: 5,
b_flag: 6,
c_flag: 7,
})
);
console.log(constants.flag_data[constants.b_flag]);
How about this solution this will work with nested objects with array as well
Object.prototype.assignOwnProVal
= function (to,from){
function compose(obj,string){
var parts = string.split('.');
var newObj = obj[parts[0]];
if(parts[1]){
parts.splice(0,1);
var newString = parts.join('.');
return compose(newObj,newString);
}
return newObj;
}
this[to] = compose(this,from);
}
var obj = { name : 'Gaurav', temp :
{id : [10,20], city:
{street:'Brunswick'}} }
obj.assignOwnProVal('street','temp.city.street');
obj.assignOwnProVal('myid','temp.id.1');
Throwing in an option since I didn't see this exact scenario covered. If you don't want c updated when a or b update, then an ES6 IIFE works well.
var foo = ((a,b) => ({
a,
b,
c: a + b
}))(a,b);
For my needs, I have an object that relates to an array which will end up being used in a loop, so I only want to calculate some common setup once, so this is what I have:
let processingState = ((indexOfSelectedTier) => ({
selectedTier,
indexOfSelectedTier,
hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier)
.some(t => pendingSelectedFiltersState[t.name]),
}))(tiers.indexOf(selectedTier));
Since I need to set a property for indexOfSelectedTier and I need to use that value when setting the hasUpperTierSelection property, I calculate that value first and pass it in as a param to the IIFE
Here is an example of behavior of 'this' in the object.
this.prop = 'external';
global.prop = 'global.prop';
const that = this;
const a = {
prop: 'internal',
prop1: this.prop, //external
log() {
return this.prop //internal
},
log1: () => {
return this.prop //external
},
log2: () => {
return function () {
return this.prop; //'global.prop' in node; 'external' in chrome
}()
},
log3: function () {
return (() => {
return this.prop; //internal
})()
},
}
I think following is best code for maintanability even though it's not in object literal syntax:
var foo = function() {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
return this;
}.call({});
This creates a new empty object with {} and then uses the anonymous function to set its properties (executed with call()). I think the only bad part is the need for return this which feels like one extra line of code. Unfortunately, I cannot figure out any nicer way to move the reference to newly created anonymous object to foo.
I think this is better than syntax var foo = new function() {...} because this one doesn't create one extra level in the prototype chain as explained by #Bergi in the comments in one of the existing answers.
However, if this is truly literal without any other logic but one addition, it would make more sense to just write
const foo = {
a:5,
b:6,
c:11, // sum of a + b
};
because there's no need to calculate that sum during runtime or even compile time.
Ok I came up with another solution. Here I want to initialize an object representing the amount of milliseconds for each unit of time.
It turns out enum in typescript can not be used in my case, so I declared multiple variables that I assign to an object as follow:
const SECOND = 1000
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
const WEEK = 7 * DAY
export const TimeInMS = {
SECOND,
MINUTE,
HOUR,
DAY,
WEEK
}
The drawbacks of this method are:
variables are defined as constants, even if we dont need them. Thus it needs useless memory.
each value of the object must be declared as standalone variable
Alternative syntax with pretty good maintanability:
let a = 5;
let b = 6;
let foo = {
a,
b,
c: a+b,
};
This works because JavaScript will use the variable name as the property name for the newly created object if you don't specify the name explicitly. For a short array like this, I'd personally go with single line syntax with return if this were inside a function:
let a = 5;
let b = 6;
return { a, b, c:a+b };
Note: This solution uses Typescript (you can use the vanilla JS which TS compiles to if needed)
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
// this method is just to check/test this solution
check(){
console.log(this.def.qwe);
}
}
// these two lines are just to check
let instance = new asd();
instance.check();
Here were using class expressions to get the nested object literal interface we'd want. This is the next best thing IMHO to being able to reference the properties of an object during creation.
Main thing to note is while using this solution, you have exact same interface as you'd have had from an object literal. And the syntax is pretty close to an object literal itself (vs using a function, etc).
Compare the following
Solution I've proposed
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
Solution if object literals would've sufficed
var asd = {
def : {
ads:'asd',
qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
}
}
Another example
Here in this class, you can combine multiple relative path among themselves, which is not possible with an object literal.
class CONSTANT {
static readonly PATH = new class {
/** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
*
*/
private readonly RELATIVE = new class {
readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
};
}
}
Other approach would be to declare the object first before assigning properties into it:
const foo = {};
foo.a = 5;
foo.b = 6;
foo.c = foo.a + foo.b; // Does work
foo.getSum = () => foo.a + foo.b + foo.c; // foo.getSum() === 22
With that, you can use the object variable name to access the already assigned values.
Best for config.js file.
If you want to use native JS, the other answers provide good solutions.
But if you're willing to write self-referencing objects like:
{
a: ...,
b: "${this.a + this.a}",
}
I wrote an npm library called self-referenced-object that supports that syntax and returns a native object.
Two lazy solutions
There are already excellent answers here and I'm no expert on this, but I am an expert in being lazy and to my expert eye these answers don't seem lazy enough.
First: return object from anonymous function
A very slight variation from T.J. Crowder, Henry Wrightson and Rafael Rocha answers:
var foo = (() => {
// Paste in your original object
const foo = {
a: 5,
b: 6,
};
// Use their properties
foo.c = foo.a + foo.b;
// Do whatever else you want
// Finally, return object
return foo;
})();
console.log(foo);
The slight advantage here is just pasting your original object as it was, without worrying about arguments etc. (IMHO the wrapper function becomes quite transparent this way).
Second: using setTimeout
This here may work, if you don't need foo.c right away:
var foo = {
a: 5,
b: 6,
c: setTimeout(() => foo.c = foo.a + foo.b, 0)
};
// Though, at first, foo.c will be the integer returned by setTimeout
console.log(foo);
// But if this isn't an issue, the value will be updated when time comes in the event loop
setTimeout( () => console.log(foo), 0);
var x = {
a: (window.secreta = 5),
b: (window.secretb = 6),
c: window.secreta + window.secretb
};
This is almost identical to #slicedtoad's answer, but doesn't use a function.

Calling Anonymous Function in Object with Property of Object [duplicate]

Is there any way to get something like the following to work in JavaScript?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
In the current form, this code obviously throws a reference error since this doesn't refer to foo. But is there any way to have values in an object literal's properties depend on other properties declared earlier?
Well, the only thing that I can tell you about are getter:
var foo = {
a: 5,
b: 6,
get c() {
return this.a + this.b;
}
}
console.log(foo.c) // 11
This is a syntactic extension introduced by the ECMAScript 5th Edition Specification, the syntax is supported by most modern browsers (including IE9).
You could do something like:
var foo = {
a: 5,
b: 6,
init: function() {
this.c = this.a + this.b;
return this;
}
}.init();
This would be some kind of one time initialization of the object.
Note that you are actually assigning the return value of init() to foo, therefore you have to return this.
The obvious, simple answer is missing, so for completeness:
But is there any way to have values in an object literal's properties depend on other properties declared earlier?
No. All of the solutions here defer it until after the object is created (in various ways) and then assign the third property. The simplest way is to just do this:
var foo = {
a: 5,
b: 6
};
foo.c = foo.a + foo.b;
All others are just more indirect ways to do the same thing. (Felix's is particularly clever, but requires creating and destroying a temporary function, adding complexity; and either leaves an extra property on the object or [if you delete that property] impacts the performance of subsequent property accesses on that object.)
If you need it to all be within one expression, you can do that without the temporary property:
var foo = function(o) {
o.c = o.a + o.b;
return o;
}({a: 5, b: 6});
Or of course, if you need to do this more than once:
function buildFoo(a, b) {
var o = {a: a, b: b};
o.c = o.a + o.b;
return o;
}
then where you need to use it:
var foo = buildFoo(5, 6);
Simply instantiate an anonymous function:
var foo = new function () {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
};
Now in ES6 you can create lazy cached properties. On first use the property evaluates once to become a normal static property. Result: The second time the math function overhead is skipped.
The magic is in the getter.
const foo = {
a: 5,
b: 6,
get c() {
delete this.c;
return this.c = this.a + this.b
}
};
In the arrow getter this picks up the surrounding lexical scope.
foo // {a: 5, b: 6}
foo.c // 11
foo // {a: 5, b: 6 , c: 11}
Some closure should deal with this;
var foo = function() {
var a = 5;
var b = 6;
var c = a + b;
return {
a: a,
b: b,
c: c
}
}();
All the variables declared within foo are private to foo, as you would expect with any function declaration and because they are all in scope, they all have access to each other without needing to refer to this, just as you would expect with a function. The difference is that this function returns an object that exposes the private variables and assigns that object to foo. In the end, you return just the interface you want to expose as an object with the return {} statement.
The function is then executed at the end with the () which causes the entire foo object to be evaluated, all the variables within instantiated and the return object added as properties of foo().
You could do it like this
var a, b
var foo = {
a: a = 5,
b: b = 6,
c: a + b
}
That method has proven useful to me when I had to refer to the object that a function was originally declared on. The following is a minimal example of how I used it:
function createMyObject() {
var count = 0, self
return {
a: self = {
log: function() {
console.log(count++)
return self
}
}
}
}
By defining self as the object that contains the print function you allow the function to refer to that object. This means you will not have to 'bind' the print function to an object if you need to pass it somewhere else.
If you would, instead, use this as illustrated below
function createMyObject() {
var count = 0
return {
a: {
log: function() {
console.log(count++)
return this
}
}
}
}
Then the following code will log 0, 1, 2 and then give an error
var o = createMyObject()
var log = o.a.log
o.a.log().log() // this refers to the o.a object so the chaining works
log().log() // this refers to the window object so the chaining fails!
By using the self method you guarantee that print will always return the same object regardless of the context in which the function is ran. The code above will run just fine and log 0, 1, 2 and 3 when using the self version of createMyObject().
For completion, in ES6 we've got classes (supported at the time of writing this only by latest browsers, but available in Babel, TypeScript and other transpilers)
class Foo {
constructor(){
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
}
}
const foo = new Foo();
just for the sake of thought - place object's properties out of a timeline:
var foo = {
a: function(){return 5}(),
b: function(){return 6}(),
c: function(){return this.a + this.b}
}
console.log(foo.c())
there are better answers above too. This is how I modified example code you questioned with.
UPDATE:
var foo = {
get a(){return 5},
get b(){return 6},
get c(){return this.a + this.b}
}
// console.log(foo.c);
You can do it using the module pattern. Just like:
var foo = function() {
var that = {};
that.a = 7;
that.b = 6;
that.c = function() {
return that.a + that.b;
}
return that;
};
var fooObject = foo();
fooObject.c(); //13
With this pattern you can instantiate several foo objects according to your need.
http://jsfiddle.net/jPNxY/1/
There are several ways to accomplish this; this is what I would use:
function Obj() {
this.a = 5;
this.b = this.a + 1;
// return this; // commented out because this happens automatically
}
var o = new Obj();
o.b; // === 6
The get property works great, and you can also use a binded closure for "expensive" functions that should only run once (this only works with var, not with const or let)
var info = {
address: (function() {
return databaseLookup(this.id)
}).bind(info)(),
get fullName() {
console.log('computing fullName...')
return `${this.first} ${this.last}`
},
id: '555-22-9999',
first: 'First',
last: 'Last',
}
function databaseLookup() {
console.log('fetching address from remote server (runs once)...')
return Promise.resolve(`22 Main St, City, Country`)
}
// test
(async () => {
console.log(info.fullName)
console.log(info.fullName)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
})()
Creating new function on your object literal and invoking a constructor seems a radical departure from the original problem, and it's unnecessary.
You cannot reference a sibling property during object literal initialization.
var x = { a: 1, b: 2, c: a + b } // not defined
var y = { a: 1, b: 2, c: y.a + y.b } // not defined
The simplest solution for computed properties follows (no heap, no functions, no constructor):
var x = { a: 1, b: 2 };
x.c = x.a + x.b; // apply computed property
I use the following code as alternative, and it works. And the variable can be array too. (# Fausto R.)
var foo = {
a: 5,
b: 6,
c: function() {
return this.a + this.b;
},
d: [10,20,30],
e: function(x) {
this.d.push(x);
return this.d;
}
};
foo.c(); // 11
foo.e(40); // foo.d = [10,20,30,40]
Just for everyone's amusement:
var foo = ( (This={
a: 5,
b: 6, })=>({...This,
c: This.a + This.b }))(
);
console.log(foo);
The other answers posted here are better but here's an alternative that:
Sets the value at initialization (not a getter, or derived, etc)
Doesn't require any type of init() or code outside of the object literal
Is an object literal and not a factory function or other object creation mechanic.
Shouldn't have any performance impact (except at initialization)
Self-executing anonymous functions and window storage
var foo = {
bar:(function(){
window.temp = "qwert";
return window.temp;
})(),
baz: window.temp
};
The order is guaranteed (bar before baz).
It pollutes window of course, but I can't imagine someone writing a script that requires window.temp to be persistent. Maybe tempMyApp if you're paranoid.
It's also ugly but occasionally useful. An example is when you are using an API with rigid initialization conditions and don't feel like refactoring so the scoping is correct.
And it's dry, of course.
The key to all this is SCOPE.
You need to encapsulate the "parent" (parent object) of the property you want to define as it's own instantiated object, and then you can make references to sibling properties using the key word this
It's very, very important to remember that if you refer to this without first so doing, then this will refer to the outer scope... which will be the window object.
var x = 9 //this is really window.x
var bar = {
x: 1,
y: 2,
foo: new function(){
this.a = 5, //assign value
this.b = 6,
this.c = this.a + this.b; // 11
},
z: this.x // 9 (not 1 as you might expect, b/c *this* refers `window` object)
};
if your object is written as a function which returns an object, AND you use ES6 object-attribute 'methods', then it's possible:
const module = (state) => ({
a: 1,
oneThing() {
state.b = state.b + this.a
},
anotherThing() {
this.oneThing();
state.c = state.b + this.a
},
});
const store = {b: 10};
const root = module(store);
root.oneThing();
console.log(store);
root.anotherThing();
console.log(store);
console.log(root, Object.keys(root), root.prototype);
Here's a neat ES6 way:
var foo = (o => ({
...o,
c: o.a + o.b
}))({
a: 5,
b: 6
});
console.log(foo);
I use it to do something like this:
const constants = Object.freeze(
(_ => ({
..._,
flag_data: {
[_.a_flag]: 'foo',
[_.b_flag]: 'bar',
[_.c_flag]: 'oof'
}
}))({
a_flag: 5,
b_flag: 6,
c_flag: 7,
})
);
console.log(constants.flag_data[constants.b_flag]);
How about this solution this will work with nested objects with array as well
Object.prototype.assignOwnProVal
= function (to,from){
function compose(obj,string){
var parts = string.split('.');
var newObj = obj[parts[0]];
if(parts[1]){
parts.splice(0,1);
var newString = parts.join('.');
return compose(newObj,newString);
}
return newObj;
}
this[to] = compose(this,from);
}
var obj = { name : 'Gaurav', temp :
{id : [10,20], city:
{street:'Brunswick'}} }
obj.assignOwnProVal('street','temp.city.street');
obj.assignOwnProVal('myid','temp.id.1');
Throwing in an option since I didn't see this exact scenario covered. If you don't want c updated when a or b update, then an ES6 IIFE works well.
var foo = ((a,b) => ({
a,
b,
c: a + b
}))(a,b);
For my needs, I have an object that relates to an array which will end up being used in a loop, so I only want to calculate some common setup once, so this is what I have:
let processingState = ((indexOfSelectedTier) => ({
selectedTier,
indexOfSelectedTier,
hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier)
.some(t => pendingSelectedFiltersState[t.name]),
}))(tiers.indexOf(selectedTier));
Since I need to set a property for indexOfSelectedTier and I need to use that value when setting the hasUpperTierSelection property, I calculate that value first and pass it in as a param to the IIFE
Here is an example of behavior of 'this' in the object.
this.prop = 'external';
global.prop = 'global.prop';
const that = this;
const a = {
prop: 'internal',
prop1: this.prop, //external
log() {
return this.prop //internal
},
log1: () => {
return this.prop //external
},
log2: () => {
return function () {
return this.prop; //'global.prop' in node; 'external' in chrome
}()
},
log3: function () {
return (() => {
return this.prop; //internal
})()
},
}
I think following is best code for maintanability even though it's not in object literal syntax:
var foo = function() {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
return this;
}.call({});
This creates a new empty object with {} and then uses the anonymous function to set its properties (executed with call()). I think the only bad part is the need for return this which feels like one extra line of code. Unfortunately, I cannot figure out any nicer way to move the reference to newly created anonymous object to foo.
I think this is better than syntax var foo = new function() {...} because this one doesn't create one extra level in the prototype chain as explained by #Bergi in the comments in one of the existing answers.
However, if this is truly literal without any other logic but one addition, it would make more sense to just write
const foo = {
a:5,
b:6,
c:11, // sum of a + b
};
because there's no need to calculate that sum during runtime or even compile time.
Ok I came up with another solution. Here I want to initialize an object representing the amount of milliseconds for each unit of time.
It turns out enum in typescript can not be used in my case, so I declared multiple variables that I assign to an object as follow:
const SECOND = 1000
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
const WEEK = 7 * DAY
export const TimeInMS = {
SECOND,
MINUTE,
HOUR,
DAY,
WEEK
}
The drawbacks of this method are:
variables are defined as constants, even if we dont need them. Thus it needs useless memory.
each value of the object must be declared as standalone variable
Alternative syntax with pretty good maintanability:
let a = 5;
let b = 6;
let foo = {
a,
b,
c: a+b,
};
This works because JavaScript will use the variable name as the property name for the newly created object if you don't specify the name explicitly. For a short array like this, I'd personally go with single line syntax with return if this were inside a function:
let a = 5;
let b = 6;
return { a, b, c:a+b };
Note: This solution uses Typescript (you can use the vanilla JS which TS compiles to if needed)
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
// this method is just to check/test this solution
check(){
console.log(this.def.qwe);
}
}
// these two lines are just to check
let instance = new asd();
instance.check();
Here were using class expressions to get the nested object literal interface we'd want. This is the next best thing IMHO to being able to reference the properties of an object during creation.
Main thing to note is while using this solution, you have exact same interface as you'd have had from an object literal. And the syntax is pretty close to an object literal itself (vs using a function, etc).
Compare the following
Solution I've proposed
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
Solution if object literals would've sufficed
var asd = {
def : {
ads:'asd',
qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
}
}
Another example
Here in this class, you can combine multiple relative path among themselves, which is not possible with an object literal.
class CONSTANT {
static readonly PATH = new class {
/** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
*
*/
private readonly RELATIVE = new class {
readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
};
}
}
Other approach would be to declare the object first before assigning properties into it:
const foo = {};
foo.a = 5;
foo.b = 6;
foo.c = foo.a + foo.b; // Does work
foo.getSum = () => foo.a + foo.b + foo.c; // foo.getSum() === 22
With that, you can use the object variable name to access the already assigned values.
Best for config.js file.
If you want to use native JS, the other answers provide good solutions.
But if you're willing to write self-referencing objects like:
{
a: ...,
b: "${this.a + this.a}",
}
I wrote an npm library called self-referenced-object that supports that syntax and returns a native object.
Two lazy solutions
There are already excellent answers here and I'm no expert on this, but I am an expert in being lazy and to my expert eye these answers don't seem lazy enough.
First: return object from anonymous function
A very slight variation from T.J. Crowder, Henry Wrightson and Rafael Rocha answers:
var foo = (() => {
// Paste in your original object
const foo = {
a: 5,
b: 6,
};
// Use their properties
foo.c = foo.a + foo.b;
// Do whatever else you want
// Finally, return object
return foo;
})();
console.log(foo);
The slight advantage here is just pasting your original object as it was, without worrying about arguments etc. (IMHO the wrapper function becomes quite transparent this way).
Second: using setTimeout
This here may work, if you don't need foo.c right away:
var foo = {
a: 5,
b: 6,
c: setTimeout(() => foo.c = foo.a + foo.b, 0)
};
// Though, at first, foo.c will be the integer returned by setTimeout
console.log(foo);
// But if this isn't an issue, the value will be updated when time comes in the event loop
setTimeout( () => console.log(foo), 0);
var x = {
a: (window.secreta = 5),
b: (window.secretb = 6),
c: window.secreta + window.secretb
};
This is almost identical to #slicedtoad's answer, but doesn't use a function.

referencing a property inside object literal [duplicate]

Is there any way to get something like the following to work in JavaScript?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
In the current form, this code obviously throws a reference error since this doesn't refer to foo. But is there any way to have values in an object literal's properties depend on other properties declared earlier?
Well, the only thing that I can tell you about are getter:
var foo = {
a: 5,
b: 6,
get c() {
return this.a + this.b;
}
}
console.log(foo.c) // 11
This is a syntactic extension introduced by the ECMAScript 5th Edition Specification, the syntax is supported by most modern browsers (including IE9).
You could do something like:
var foo = {
a: 5,
b: 6,
init: function() {
this.c = this.a + this.b;
return this;
}
}.init();
This would be some kind of one time initialization of the object.
Note that you are actually assigning the return value of init() to foo, therefore you have to return this.
The obvious, simple answer is missing, so for completeness:
But is there any way to have values in an object literal's properties depend on other properties declared earlier?
No. All of the solutions here defer it until after the object is created (in various ways) and then assign the third property. The simplest way is to just do this:
var foo = {
a: 5,
b: 6
};
foo.c = foo.a + foo.b;
All others are just more indirect ways to do the same thing. (Felix's is particularly clever, but requires creating and destroying a temporary function, adding complexity; and either leaves an extra property on the object or [if you delete that property] impacts the performance of subsequent property accesses on that object.)
If you need it to all be within one expression, you can do that without the temporary property:
var foo = function(o) {
o.c = o.a + o.b;
return o;
}({a: 5, b: 6});
Or of course, if you need to do this more than once:
function buildFoo(a, b) {
var o = {a: a, b: b};
o.c = o.a + o.b;
return o;
}
then where you need to use it:
var foo = buildFoo(5, 6);
Simply instantiate an anonymous function:
var foo = new function () {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
};
Now in ES6 you can create lazy cached properties. On first use the property evaluates once to become a normal static property. Result: The second time the math function overhead is skipped.
The magic is in the getter.
const foo = {
a: 5,
b: 6,
get c() {
delete this.c;
return this.c = this.a + this.b
}
};
In the arrow getter this picks up the surrounding lexical scope.
foo // {a: 5, b: 6}
foo.c // 11
foo // {a: 5, b: 6 , c: 11}
Some closure should deal with this;
var foo = function() {
var a = 5;
var b = 6;
var c = a + b;
return {
a: a,
b: b,
c: c
}
}();
All the variables declared within foo are private to foo, as you would expect with any function declaration and because they are all in scope, they all have access to each other without needing to refer to this, just as you would expect with a function. The difference is that this function returns an object that exposes the private variables and assigns that object to foo. In the end, you return just the interface you want to expose as an object with the return {} statement.
The function is then executed at the end with the () which causes the entire foo object to be evaluated, all the variables within instantiated and the return object added as properties of foo().
You could do it like this
var a, b
var foo = {
a: a = 5,
b: b = 6,
c: a + b
}
That method has proven useful to me when I had to refer to the object that a function was originally declared on. The following is a minimal example of how I used it:
function createMyObject() {
var count = 0, self
return {
a: self = {
log: function() {
console.log(count++)
return self
}
}
}
}
By defining self as the object that contains the print function you allow the function to refer to that object. This means you will not have to 'bind' the print function to an object if you need to pass it somewhere else.
If you would, instead, use this as illustrated below
function createMyObject() {
var count = 0
return {
a: {
log: function() {
console.log(count++)
return this
}
}
}
}
Then the following code will log 0, 1, 2 and then give an error
var o = createMyObject()
var log = o.a.log
o.a.log().log() // this refers to the o.a object so the chaining works
log().log() // this refers to the window object so the chaining fails!
By using the self method you guarantee that print will always return the same object regardless of the context in which the function is ran. The code above will run just fine and log 0, 1, 2 and 3 when using the self version of createMyObject().
For completion, in ES6 we've got classes (supported at the time of writing this only by latest browsers, but available in Babel, TypeScript and other transpilers)
class Foo {
constructor(){
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
}
}
const foo = new Foo();
just for the sake of thought - place object's properties out of a timeline:
var foo = {
a: function(){return 5}(),
b: function(){return 6}(),
c: function(){return this.a + this.b}
}
console.log(foo.c())
there are better answers above too. This is how I modified example code you questioned with.
UPDATE:
var foo = {
get a(){return 5},
get b(){return 6},
get c(){return this.a + this.b}
}
// console.log(foo.c);
You can do it using the module pattern. Just like:
var foo = function() {
var that = {};
that.a = 7;
that.b = 6;
that.c = function() {
return that.a + that.b;
}
return that;
};
var fooObject = foo();
fooObject.c(); //13
With this pattern you can instantiate several foo objects according to your need.
http://jsfiddle.net/jPNxY/1/
There are several ways to accomplish this; this is what I would use:
function Obj() {
this.a = 5;
this.b = this.a + 1;
// return this; // commented out because this happens automatically
}
var o = new Obj();
o.b; // === 6
The get property works great, and you can also use a binded closure for "expensive" functions that should only run once (this only works with var, not with const or let)
var info = {
address: (function() {
return databaseLookup(this.id)
}).bind(info)(),
get fullName() {
console.log('computing fullName...')
return `${this.first} ${this.last}`
},
id: '555-22-9999',
first: 'First',
last: 'Last',
}
function databaseLookup() {
console.log('fetching address from remote server (runs once)...')
return Promise.resolve(`22 Main St, City, Country`)
}
// test
(async () => {
console.log(info.fullName)
console.log(info.fullName)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
})()
Creating new function on your object literal and invoking a constructor seems a radical departure from the original problem, and it's unnecessary.
You cannot reference a sibling property during object literal initialization.
var x = { a: 1, b: 2, c: a + b } // not defined
var y = { a: 1, b: 2, c: y.a + y.b } // not defined
The simplest solution for computed properties follows (no heap, no functions, no constructor):
var x = { a: 1, b: 2 };
x.c = x.a + x.b; // apply computed property
I use the following code as alternative, and it works. And the variable can be array too. (# Fausto R.)
var foo = {
a: 5,
b: 6,
c: function() {
return this.a + this.b;
},
d: [10,20,30],
e: function(x) {
this.d.push(x);
return this.d;
}
};
foo.c(); // 11
foo.e(40); // foo.d = [10,20,30,40]
Just for everyone's amusement:
var foo = ( (This={
a: 5,
b: 6, })=>({...This,
c: This.a + This.b }))(
);
console.log(foo);
The other answers posted here are better but here's an alternative that:
Sets the value at initialization (not a getter, or derived, etc)
Doesn't require any type of init() or code outside of the object literal
Is an object literal and not a factory function or other object creation mechanic.
Shouldn't have any performance impact (except at initialization)
Self-executing anonymous functions and window storage
var foo = {
bar:(function(){
window.temp = "qwert";
return window.temp;
})(),
baz: window.temp
};
The order is guaranteed (bar before baz).
It pollutes window of course, but I can't imagine someone writing a script that requires window.temp to be persistent. Maybe tempMyApp if you're paranoid.
It's also ugly but occasionally useful. An example is when you are using an API with rigid initialization conditions and don't feel like refactoring so the scoping is correct.
And it's dry, of course.
The key to all this is SCOPE.
You need to encapsulate the "parent" (parent object) of the property you want to define as it's own instantiated object, and then you can make references to sibling properties using the key word this
It's very, very important to remember that if you refer to this without first so doing, then this will refer to the outer scope... which will be the window object.
var x = 9 //this is really window.x
var bar = {
x: 1,
y: 2,
foo: new function(){
this.a = 5, //assign value
this.b = 6,
this.c = this.a + this.b; // 11
},
z: this.x // 9 (not 1 as you might expect, b/c *this* refers `window` object)
};
if your object is written as a function which returns an object, AND you use ES6 object-attribute 'methods', then it's possible:
const module = (state) => ({
a: 1,
oneThing() {
state.b = state.b + this.a
},
anotherThing() {
this.oneThing();
state.c = state.b + this.a
},
});
const store = {b: 10};
const root = module(store);
root.oneThing();
console.log(store);
root.anotherThing();
console.log(store);
console.log(root, Object.keys(root), root.prototype);
Here's a neat ES6 way:
var foo = (o => ({
...o,
c: o.a + o.b
}))({
a: 5,
b: 6
});
console.log(foo);
I use it to do something like this:
const constants = Object.freeze(
(_ => ({
..._,
flag_data: {
[_.a_flag]: 'foo',
[_.b_flag]: 'bar',
[_.c_flag]: 'oof'
}
}))({
a_flag: 5,
b_flag: 6,
c_flag: 7,
})
);
console.log(constants.flag_data[constants.b_flag]);
How about this solution this will work with nested objects with array as well
Object.prototype.assignOwnProVal
= function (to,from){
function compose(obj,string){
var parts = string.split('.');
var newObj = obj[parts[0]];
if(parts[1]){
parts.splice(0,1);
var newString = parts.join('.');
return compose(newObj,newString);
}
return newObj;
}
this[to] = compose(this,from);
}
var obj = { name : 'Gaurav', temp :
{id : [10,20], city:
{street:'Brunswick'}} }
obj.assignOwnProVal('street','temp.city.street');
obj.assignOwnProVal('myid','temp.id.1');
Throwing in an option since I didn't see this exact scenario covered. If you don't want c updated when a or b update, then an ES6 IIFE works well.
var foo = ((a,b) => ({
a,
b,
c: a + b
}))(a,b);
For my needs, I have an object that relates to an array which will end up being used in a loop, so I only want to calculate some common setup once, so this is what I have:
let processingState = ((indexOfSelectedTier) => ({
selectedTier,
indexOfSelectedTier,
hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier)
.some(t => pendingSelectedFiltersState[t.name]),
}))(tiers.indexOf(selectedTier));
Since I need to set a property for indexOfSelectedTier and I need to use that value when setting the hasUpperTierSelection property, I calculate that value first and pass it in as a param to the IIFE
Here is an example of behavior of 'this' in the object.
this.prop = 'external';
global.prop = 'global.prop';
const that = this;
const a = {
prop: 'internal',
prop1: this.prop, //external
log() {
return this.prop //internal
},
log1: () => {
return this.prop //external
},
log2: () => {
return function () {
return this.prop; //'global.prop' in node; 'external' in chrome
}()
},
log3: function () {
return (() => {
return this.prop; //internal
})()
},
}
I think following is best code for maintanability even though it's not in object literal syntax:
var foo = function() {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
return this;
}.call({});
This creates a new empty object with {} and then uses the anonymous function to set its properties (executed with call()). I think the only bad part is the need for return this which feels like one extra line of code. Unfortunately, I cannot figure out any nicer way to move the reference to newly created anonymous object to foo.
I think this is better than syntax var foo = new function() {...} because this one doesn't create one extra level in the prototype chain as explained by #Bergi in the comments in one of the existing answers.
However, if this is truly literal without any other logic but one addition, it would make more sense to just write
const foo = {
a:5,
b:6,
c:11, // sum of a + b
};
because there's no need to calculate that sum during runtime or even compile time.
Ok I came up with another solution. Here I want to initialize an object representing the amount of milliseconds for each unit of time.
It turns out enum in typescript can not be used in my case, so I declared multiple variables that I assign to an object as follow:
const SECOND = 1000
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
const WEEK = 7 * DAY
export const TimeInMS = {
SECOND,
MINUTE,
HOUR,
DAY,
WEEK
}
The drawbacks of this method are:
variables are defined as constants, even if we dont need them. Thus it needs useless memory.
each value of the object must be declared as standalone variable
Alternative syntax with pretty good maintanability:
let a = 5;
let b = 6;
let foo = {
a,
b,
c: a+b,
};
This works because JavaScript will use the variable name as the property name for the newly created object if you don't specify the name explicitly. For a short array like this, I'd personally go with single line syntax with return if this were inside a function:
let a = 5;
let b = 6;
return { a, b, c:a+b };
Note: This solution uses Typescript (you can use the vanilla JS which TS compiles to if needed)
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
// this method is just to check/test this solution
check(){
console.log(this.def.qwe);
}
}
// these two lines are just to check
let instance = new asd();
instance.check();
Here were using class expressions to get the nested object literal interface we'd want. This is the next best thing IMHO to being able to reference the properties of an object during creation.
Main thing to note is while using this solution, you have exact same interface as you'd have had from an object literal. And the syntax is pretty close to an object literal itself (vs using a function, etc).
Compare the following
Solution I've proposed
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
Solution if object literals would've sufficed
var asd = {
def : {
ads:'asd',
qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
}
}
Another example
Here in this class, you can combine multiple relative path among themselves, which is not possible with an object literal.
class CONSTANT {
static readonly PATH = new class {
/** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
*
*/
private readonly RELATIVE = new class {
readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
};
}
}
Other approach would be to declare the object first before assigning properties into it:
const foo = {};
foo.a = 5;
foo.b = 6;
foo.c = foo.a + foo.b; // Does work
foo.getSum = () => foo.a + foo.b + foo.c; // foo.getSum() === 22
With that, you can use the object variable name to access the already assigned values.
Best for config.js file.
If you want to use native JS, the other answers provide good solutions.
But if you're willing to write self-referencing objects like:
{
a: ...,
b: "${this.a + this.a}",
}
I wrote an npm library called self-referenced-object that supports that syntax and returns a native object.
Two lazy solutions
There are already excellent answers here and I'm no expert on this, but I am an expert in being lazy and to my expert eye these answers don't seem lazy enough.
First: return object from anonymous function
A very slight variation from T.J. Crowder, Henry Wrightson and Rafael Rocha answers:
var foo = (() => {
// Paste in your original object
const foo = {
a: 5,
b: 6,
};
// Use their properties
foo.c = foo.a + foo.b;
// Do whatever else you want
// Finally, return object
return foo;
})();
console.log(foo);
The slight advantage here is just pasting your original object as it was, without worrying about arguments etc. (IMHO the wrapper function becomes quite transparent this way).
Second: using setTimeout
This here may work, if you don't need foo.c right away:
var foo = {
a: 5,
b: 6,
c: setTimeout(() => foo.c = foo.a + foo.b, 0)
};
// Though, at first, foo.c will be the integer returned by setTimeout
console.log(foo);
// But if this isn't an issue, the value will be updated when time comes in the event loop
setTimeout( () => console.log(foo), 0);
var x = {
a: (window.secreta = 5),
b: (window.secretb = 6),
c: window.secreta + window.secretb
};
This is almost identical to #slicedtoad's answer, but doesn't use a function.

Object property referenced within the same object [duplicate]

Is there any way to get something like the following to work in JavaScript?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
In the current form, this code obviously throws a reference error since this doesn't refer to foo. But is there any way to have values in an object literal's properties depend on other properties declared earlier?
Well, the only thing that I can tell you about are getter:
var foo = {
a: 5,
b: 6,
get c() {
return this.a + this.b;
}
}
console.log(foo.c) // 11
This is a syntactic extension introduced by the ECMAScript 5th Edition Specification, the syntax is supported by most modern browsers (including IE9).
You could do something like:
var foo = {
a: 5,
b: 6,
init: function() {
this.c = this.a + this.b;
return this;
}
}.init();
This would be some kind of one time initialization of the object.
Note that you are actually assigning the return value of init() to foo, therefore you have to return this.
The obvious, simple answer is missing, so for completeness:
But is there any way to have values in an object literal's properties depend on other properties declared earlier?
No. All of the solutions here defer it until after the object is created (in various ways) and then assign the third property. The simplest way is to just do this:
var foo = {
a: 5,
b: 6
};
foo.c = foo.a + foo.b;
All others are just more indirect ways to do the same thing. (Felix's is particularly clever, but requires creating and destroying a temporary function, adding complexity; and either leaves an extra property on the object or [if you delete that property] impacts the performance of subsequent property accesses on that object.)
If you need it to all be within one expression, you can do that without the temporary property:
var foo = function(o) {
o.c = o.a + o.b;
return o;
}({a: 5, b: 6});
Or of course, if you need to do this more than once:
function buildFoo(a, b) {
var o = {a: a, b: b};
o.c = o.a + o.b;
return o;
}
then where you need to use it:
var foo = buildFoo(5, 6);
Simply instantiate an anonymous function:
var foo = new function () {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
};
Now in ES6 you can create lazy cached properties. On first use the property evaluates once to become a normal static property. Result: The second time the math function overhead is skipped.
The magic is in the getter.
const foo = {
a: 5,
b: 6,
get c() {
delete this.c;
return this.c = this.a + this.b
}
};
In the arrow getter this picks up the surrounding lexical scope.
foo // {a: 5, b: 6}
foo.c // 11
foo // {a: 5, b: 6 , c: 11}
Some closure should deal with this;
var foo = function() {
var a = 5;
var b = 6;
var c = a + b;
return {
a: a,
b: b,
c: c
}
}();
All the variables declared within foo are private to foo, as you would expect with any function declaration and because they are all in scope, they all have access to each other without needing to refer to this, just as you would expect with a function. The difference is that this function returns an object that exposes the private variables and assigns that object to foo. In the end, you return just the interface you want to expose as an object with the return {} statement.
The function is then executed at the end with the () which causes the entire foo object to be evaluated, all the variables within instantiated and the return object added as properties of foo().
You could do it like this
var a, b
var foo = {
a: a = 5,
b: b = 6,
c: a + b
}
That method has proven useful to me when I had to refer to the object that a function was originally declared on. The following is a minimal example of how I used it:
function createMyObject() {
var count = 0, self
return {
a: self = {
log: function() {
console.log(count++)
return self
}
}
}
}
By defining self as the object that contains the print function you allow the function to refer to that object. This means you will not have to 'bind' the print function to an object if you need to pass it somewhere else.
If you would, instead, use this as illustrated below
function createMyObject() {
var count = 0
return {
a: {
log: function() {
console.log(count++)
return this
}
}
}
}
Then the following code will log 0, 1, 2 and then give an error
var o = createMyObject()
var log = o.a.log
o.a.log().log() // this refers to the o.a object so the chaining works
log().log() // this refers to the window object so the chaining fails!
By using the self method you guarantee that print will always return the same object regardless of the context in which the function is ran. The code above will run just fine and log 0, 1, 2 and 3 when using the self version of createMyObject().
For completion, in ES6 we've got classes (supported at the time of writing this only by latest browsers, but available in Babel, TypeScript and other transpilers)
class Foo {
constructor(){
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
}
}
const foo = new Foo();
just for the sake of thought - place object's properties out of a timeline:
var foo = {
a: function(){return 5}(),
b: function(){return 6}(),
c: function(){return this.a + this.b}
}
console.log(foo.c())
there are better answers above too. This is how I modified example code you questioned with.
UPDATE:
var foo = {
get a(){return 5},
get b(){return 6},
get c(){return this.a + this.b}
}
// console.log(foo.c);
You can do it using the module pattern. Just like:
var foo = function() {
var that = {};
that.a = 7;
that.b = 6;
that.c = function() {
return that.a + that.b;
}
return that;
};
var fooObject = foo();
fooObject.c(); //13
With this pattern you can instantiate several foo objects according to your need.
http://jsfiddle.net/jPNxY/1/
There are several ways to accomplish this; this is what I would use:
function Obj() {
this.a = 5;
this.b = this.a + 1;
// return this; // commented out because this happens automatically
}
var o = new Obj();
o.b; // === 6
The get property works great, and you can also use a binded closure for "expensive" functions that should only run once (this only works with var, not with const or let)
var info = {
address: (function() {
return databaseLookup(this.id)
}).bind(info)(),
get fullName() {
console.log('computing fullName...')
return `${this.first} ${this.last}`
},
id: '555-22-9999',
first: 'First',
last: 'Last',
}
function databaseLookup() {
console.log('fetching address from remote server (runs once)...')
return Promise.resolve(`22 Main St, City, Country`)
}
// test
(async () => {
console.log(info.fullName)
console.log(info.fullName)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
})()
Creating new function on your object literal and invoking a constructor seems a radical departure from the original problem, and it's unnecessary.
You cannot reference a sibling property during object literal initialization.
var x = { a: 1, b: 2, c: a + b } // not defined
var y = { a: 1, b: 2, c: y.a + y.b } // not defined
The simplest solution for computed properties follows (no heap, no functions, no constructor):
var x = { a: 1, b: 2 };
x.c = x.a + x.b; // apply computed property
I use the following code as alternative, and it works. And the variable can be array too. (# Fausto R.)
var foo = {
a: 5,
b: 6,
c: function() {
return this.a + this.b;
},
d: [10,20,30],
e: function(x) {
this.d.push(x);
return this.d;
}
};
foo.c(); // 11
foo.e(40); // foo.d = [10,20,30,40]
Just for everyone's amusement:
var foo = ( (This={
a: 5,
b: 6, })=>({...This,
c: This.a + This.b }))(
);
console.log(foo);
The other answers posted here are better but here's an alternative that:
Sets the value at initialization (not a getter, or derived, etc)
Doesn't require any type of init() or code outside of the object literal
Is an object literal and not a factory function or other object creation mechanic.
Shouldn't have any performance impact (except at initialization)
Self-executing anonymous functions and window storage
var foo = {
bar:(function(){
window.temp = "qwert";
return window.temp;
})(),
baz: window.temp
};
The order is guaranteed (bar before baz).
It pollutes window of course, but I can't imagine someone writing a script that requires window.temp to be persistent. Maybe tempMyApp if you're paranoid.
It's also ugly but occasionally useful. An example is when you are using an API with rigid initialization conditions and don't feel like refactoring so the scoping is correct.
And it's dry, of course.
The key to all this is SCOPE.
You need to encapsulate the "parent" (parent object) of the property you want to define as it's own instantiated object, and then you can make references to sibling properties using the key word this
It's very, very important to remember that if you refer to this without first so doing, then this will refer to the outer scope... which will be the window object.
var x = 9 //this is really window.x
var bar = {
x: 1,
y: 2,
foo: new function(){
this.a = 5, //assign value
this.b = 6,
this.c = this.a + this.b; // 11
},
z: this.x // 9 (not 1 as you might expect, b/c *this* refers `window` object)
};
if your object is written as a function which returns an object, AND you use ES6 object-attribute 'methods', then it's possible:
const module = (state) => ({
a: 1,
oneThing() {
state.b = state.b + this.a
},
anotherThing() {
this.oneThing();
state.c = state.b + this.a
},
});
const store = {b: 10};
const root = module(store);
root.oneThing();
console.log(store);
root.anotherThing();
console.log(store);
console.log(root, Object.keys(root), root.prototype);
Here's a neat ES6 way:
var foo = (o => ({
...o,
c: o.a + o.b
}))({
a: 5,
b: 6
});
console.log(foo);
I use it to do something like this:
const constants = Object.freeze(
(_ => ({
..._,
flag_data: {
[_.a_flag]: 'foo',
[_.b_flag]: 'bar',
[_.c_flag]: 'oof'
}
}))({
a_flag: 5,
b_flag: 6,
c_flag: 7,
})
);
console.log(constants.flag_data[constants.b_flag]);
How about this solution this will work with nested objects with array as well
Object.prototype.assignOwnProVal
= function (to,from){
function compose(obj,string){
var parts = string.split('.');
var newObj = obj[parts[0]];
if(parts[1]){
parts.splice(0,1);
var newString = parts.join('.');
return compose(newObj,newString);
}
return newObj;
}
this[to] = compose(this,from);
}
var obj = { name : 'Gaurav', temp :
{id : [10,20], city:
{street:'Brunswick'}} }
obj.assignOwnProVal('street','temp.city.street');
obj.assignOwnProVal('myid','temp.id.1');
Throwing in an option since I didn't see this exact scenario covered. If you don't want c updated when a or b update, then an ES6 IIFE works well.
var foo = ((a,b) => ({
a,
b,
c: a + b
}))(a,b);
For my needs, I have an object that relates to an array which will end up being used in a loop, so I only want to calculate some common setup once, so this is what I have:
let processingState = ((indexOfSelectedTier) => ({
selectedTier,
indexOfSelectedTier,
hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier)
.some(t => pendingSelectedFiltersState[t.name]),
}))(tiers.indexOf(selectedTier));
Since I need to set a property for indexOfSelectedTier and I need to use that value when setting the hasUpperTierSelection property, I calculate that value first and pass it in as a param to the IIFE
Here is an example of behavior of 'this' in the object.
this.prop = 'external';
global.prop = 'global.prop';
const that = this;
const a = {
prop: 'internal',
prop1: this.prop, //external
log() {
return this.prop //internal
},
log1: () => {
return this.prop //external
},
log2: () => {
return function () {
return this.prop; //'global.prop' in node; 'external' in chrome
}()
},
log3: function () {
return (() => {
return this.prop; //internal
})()
},
}
I think following is best code for maintanability even though it's not in object literal syntax:
var foo = function() {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
return this;
}.call({});
This creates a new empty object with {} and then uses the anonymous function to set its properties (executed with call()). I think the only bad part is the need for return this which feels like one extra line of code. Unfortunately, I cannot figure out any nicer way to move the reference to newly created anonymous object to foo.
I think this is better than syntax var foo = new function() {...} because this one doesn't create one extra level in the prototype chain as explained by #Bergi in the comments in one of the existing answers.
However, if this is truly literal without any other logic but one addition, it would make more sense to just write
const foo = {
a:5,
b:6,
c:11, // sum of a + b
};
because there's no need to calculate that sum during runtime or even compile time.
Ok I came up with another solution. Here I want to initialize an object representing the amount of milliseconds for each unit of time.
It turns out enum in typescript can not be used in my case, so I declared multiple variables that I assign to an object as follow:
const SECOND = 1000
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
const WEEK = 7 * DAY
export const TimeInMS = {
SECOND,
MINUTE,
HOUR,
DAY,
WEEK
}
The drawbacks of this method are:
variables are defined as constants, even if we dont need them. Thus it needs useless memory.
each value of the object must be declared as standalone variable
Alternative syntax with pretty good maintanability:
let a = 5;
let b = 6;
let foo = {
a,
b,
c: a+b,
};
This works because JavaScript will use the variable name as the property name for the newly created object if you don't specify the name explicitly. For a short array like this, I'd personally go with single line syntax with return if this were inside a function:
let a = 5;
let b = 6;
return { a, b, c:a+b };
Note: This solution uses Typescript (you can use the vanilla JS which TS compiles to if needed)
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
// this method is just to check/test this solution
check(){
console.log(this.def.qwe);
}
}
// these two lines are just to check
let instance = new asd();
instance.check();
Here were using class expressions to get the nested object literal interface we'd want. This is the next best thing IMHO to being able to reference the properties of an object during creation.
Main thing to note is while using this solution, you have exact same interface as you'd have had from an object literal. And the syntax is pretty close to an object literal itself (vs using a function, etc).
Compare the following
Solution I've proposed
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
Solution if object literals would've sufficed
var asd = {
def : {
ads:'asd',
qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
}
}
Another example
Here in this class, you can combine multiple relative path among themselves, which is not possible with an object literal.
class CONSTANT {
static readonly PATH = new class {
/** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
*
*/
private readonly RELATIVE = new class {
readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
};
}
}
Other approach would be to declare the object first before assigning properties into it:
const foo = {};
foo.a = 5;
foo.b = 6;
foo.c = foo.a + foo.b; // Does work
foo.getSum = () => foo.a + foo.b + foo.c; // foo.getSum() === 22
With that, you can use the object variable name to access the already assigned values.
Best for config.js file.
If you want to use native JS, the other answers provide good solutions.
But if you're willing to write self-referencing objects like:
{
a: ...,
b: "${this.a + this.a}",
}
I wrote an npm library called self-referenced-object that supports that syntax and returns a native object.
Two lazy solutions
There are already excellent answers here and I'm no expert on this, but I am an expert in being lazy and to my expert eye these answers don't seem lazy enough.
First: return object from anonymous function
A very slight variation from T.J. Crowder, Henry Wrightson and Rafael Rocha answers:
var foo = (() => {
// Paste in your original object
const foo = {
a: 5,
b: 6,
};
// Use their properties
foo.c = foo.a + foo.b;
// Do whatever else you want
// Finally, return object
return foo;
})();
console.log(foo);
The slight advantage here is just pasting your original object as it was, without worrying about arguments etc. (IMHO the wrapper function becomes quite transparent this way).
Second: using setTimeout
This here may work, if you don't need foo.c right away:
var foo = {
a: 5,
b: 6,
c: setTimeout(() => foo.c = foo.a + foo.b, 0)
};
// Though, at first, foo.c will be the integer returned by setTimeout
console.log(foo);
// But if this isn't an issue, the value will be updated when time comes in the event loop
setTimeout( () => console.log(foo), 0);
var x = {
a: (window.secreta = 5),
b: (window.secretb = 6),
c: window.secreta + window.secretb
};
This is almost identical to #slicedtoad's answer, but doesn't use a function.

Categories