Ok so I'm working away on a project in Nodes, and I've come across a small problem with the keys in object literals, I have the following set-up:
var required = {
directories : {
this.applicationPath : "Application " + this.application + " does not exists",
this.applicationPath + "/configs" : "Application config folder does not exists",
this.applicationPath + "/controllers" : "Application controllers folder does not exists",
this.applicationPath + "/public" : "Application public folder does not exists",
this.applicationPath + "/views" : "Application views folder does not exists"
},
files : {
this.applicationPath + "/init.js" : "Application init.js file does not exists",
this.applicationPath + "/controllers/index.js" : "Application index.js controller file does not exists",
this.applicationPath + "/configs/application.js": "Application configs/application.js file does not exists",
this.applicationPath + "/configs/server.js" : "Application configs/server.js file does not exists"
}
}
Ok so many of you will look at this and think it look's OK, but the compiler keeps telling me that I am missing a :
(colon), which im not, it seems like the +
or and the .
are both effecting the compiler.
Now i believe (not sure), that object literals are created at compile time, and not run-time, meaning that dynamic variables such as this.applicationPath
and concatenation are not going to be available :( :(
What's the best way to overcome an obstacle like this without having to rewrite large chunks of code.
For object literals, Javascript/ECMAScript script specifies keys be either a valid IdentifierName, a string literal, or a number credit RobG (even hex) . Not an expression, which is what
required.applicationPath + "/configs"
is.If you have a deep object structure (such as Grunt config), it's sometimes convenient to be able to return dynamically-generated object keys using the bracket notation outlined by Felix, but inline within the object structure. This can be achieved by using a function to dynamically return an object within the context of the deep object; in the case for the code in this question, something like this:
This fiddle validates this approach.
Inspired by how babel coverts the new ES6 syntax (
{[expression]: value}
) to old Javascript, I learned that you can do it with a one liner:Example:
(Tested on latest Chrome)
The only way you can set dynamic keys is with bracket notation:
(of course wherever you do this definition,
this.applicationPath
must exist)But do you need
this.applicationPath
in the keys? How do you access theses values? Maybe you can just removethis.applicationPath
from whatever value you use to access the properties.But in case you need it:
You could use an array to initialize the keys if you want to avoid repeating a lot of code:
the problem is from using 'this' because it doesn't refer to anything smart*. create the static literal with the applicationPath in it.
Then use
to fill it dynamically
Edit; I rushed with my first idea, it didn't work. The above works now - sorry for that!
* the keyword 'this' is very smart :) but it often refers to the window object or the element, the event has been fired on or the called 'active' object. Thus, creating a lot of confusion ;)
In an object literal (ECMA-262 §11.1.5 calls it an "object initialiser") the key must be one of:
So you can't use an expression as the key in an initialiser. You can use an expression with square bracket notation to access a property. So to set the properties wtih an expression you have to do:
and so on. Since
this.applicationPath
is reused a lot, better to store a reference to help with performance and cut down the amount of code:Edit
As of ECMAScript ed 6, object initializers can have computed keys using:
There is also shorthand syntax for property and method names.
See MDN: Object Initializer or ECMAScript §12.2.6.