Javascript中的对象文字的dynamic键

好,所以我在Nodes的一个项目中工作,我遇到了对象文字中的一个小问题,我有以下设置:

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" } } 

好吧,你们很多人会看这个,认为它看起来没问题,但编译器不断告诉我,我错过了一个:冒号),而不是,它似乎是+或和. 都影响编译器。

现在我相信(不知道),该对象文字是在编译时创build的,而不是运行时,这意味着dynamicvariables,如this.applicationPath和串联不会是可用的:(

克服这种障碍的最好方法是什么,而不必重写大块代码。

您可以设置dynamic键的唯一方法是使用括号表示法:

 required.directories[this.applicationPath + "/configs"] = "Application config folder does not exists"; 

(当然,无论你做这个定义, this.applicationPath必须存在)

但是,你需要在密钥中的this.applicationPath ? 你如何获得这些值? 也许你可以从你用来访问属性的任何值中删除this.applicationPath


但是,如果你需要它:

如果你想避免重复很多代码,你可以使用一个数组来初始化键:

 var dirs = ['configs', 'controllers', ...]; var files = ['init.js', 'controllers/index.js', ...]; var required = { directories: {}, files: {} }; required.directories[this.applicationPath] = "Application " + this.application + " does not exists"; for(var i = dirs.length; i--;) { required.directories[this.applicationPath + '/' + dirs[i]] = "Application " + dirs[i] + " folder does not exists"; } for(var i = files.length; i--;) { // same here } 

在对象文字(ECMA-262§11.1.5称它为“对象初始化程序”)中,键必须是下列之一:

  1. IdentifierName
  2. string字面量
  3. NumericLiteral

所以你不能在expression式中使用expression式作为关键字。 您可以使用带有方括号表示法的expression式来访问属性。 所以要设置一个expression式的属性,你必须:

 var required = { directories : {}}; required.directories[this.applicationPath] = "Application " + this.application + " does not exists"; required.directories[this.applicationPath + "/configs"] = "Application config folder does not exists"; ... 

等等。 由于this.applicationPath被重用了很多,最好存储一个引用来帮助性能和减less代码量:

 var a = this.applicationPath; var required = { directories : {}}; var rd = required.directories; rd[a] = "Application " + this.application + " does not exists"; rd[a + "/configs"] = "Application config folder does not exists"; ... 

编辑

从ECMAScript ed 6开始,对象初始值设定项可以使用以下计算键:

 [expression]: value 

还有属性和方法名称的简写语法。

请参阅MDN:对象初始化程序或ECMAScript第12.2.6节 。

计算属性名称在ECMAScript2015中受支持:

 var name = 'key'; var value = 'value'; var o = { [name]: value }; 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer

受到babel如何将新的ES6语法( {[expression]: value} ))转换为旧的Javascript的启发,我了解到可以用一行代码来完成:

 var obj = (_obj = {}, _obj[expression] = value, _obj); 

例:

 var dynamic_key = "hello"; var value = "world"; var obj = (_obj = {}, _obj[dynamic_key] = value, _obj); console.log(obj); // Object {hello: "world"} 

(经过最新的Chrometesting)

对于对象文字,Javascript / ECMAScript脚本指定的键是一个有效的IdentifierName,一个string文字或一个数字RobG (hex)。 不是expression式,这是什么required.applicationPath + "/configs"是。

如果你有一个深层的对象结构(比如Grunt config),使用Felix概括的括号表示返回dynamic生成的对象键,但在对象结构中内联有时很方便。 这可以通过使用函数来dynamic地返回深对象的上下文中的对象来实现; 在这个问题的代码的情况下,这样的事情:

 var required = { directories : function() { var o = {}; o[this.applicationPath] = "Application " + this.application + " does not exists"; o[this.applicationPath + "/configs"] = "Application config folder does not exists"; o[this.applicationPath + "/controllers"] = "Application controllers folder does not exists"; o[this.applicationPath + "/public"] = "Application public folder does not exists"; o[this.applicationPath + "/views"] = "Application views folder does not exists"; return o; }(), files : function() { var o = {}; o[this.applicationPath + "/init.js"] = "Application init.js file does not exists"; o[this.applicationPath + "/controllers/index.js"] = "Application index.js controller file does not exists"; o[this.applicationPath + "/configs/application.js"] ="Application configs/application.js file does not exists"; o[this.applicationPath + "/configs/server.js"] ="Application configs/server.js file does not exists"; return o; }() } 

这小提琴validation这种方法。

一个古老的问题,当时的答案是正确的,但时代变了。 如果有人在谷歌search中挖掘它,新的JavaScript版本(ES6)允许使用expression式作为对象字面值的关键字,如果它们被括在方括号中: var obj={["a"+Math.PI]:42}

问题在于使用“this”,因为它并不涉及任何智能*。 用applicationPath创build静态文字。

 var required = {
     “applicationPath”: “someWhereOverTheRainboW”
 };

然后使用

 required.directories = {};
 required.directories [required.applicationPath +“/ configs”] =“应用程序configuration文件夹不存在”;
 ....

以dynamic填充它

编辑; 我冲我的第一个想法,这是行不通的。 上面的作品现在 – 对不起!

*关键字'this'非常聪明:)但它通常指的是窗口对象或元素,事件已经被触发或被调用的“活动”对象。 因此,造成了很多混乱;)