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称它为“对象初始化程序”)中,键必须是下列之一:
- IdentifierName
- string字面量
- 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'非常聪明:)但它通常指的是窗口对象或元素,事件已经被触发或被调用的“活动”对象。 因此,造成了很多混乱;)