Javascript 中对象字面量的动态键
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6500573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
dynamic keys for object literals in Javascript
提问by RobertPitt
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:
好的,所以我正在 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"
}
}
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.
好吧,你们中的许多人会看到这个并认为它看起来不错,但是编译器一直告诉我我缺少一个:
(冒号),我没有,似乎+
or 和 the.
都影响编译器。
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 :( :(
现在我相信(不确定),对象文字是在编译时创建的,而不是在运行时创建的,这意味着诸如this.applicationPath
和 连接之类的动态变量将不可用:( :(
What's the best way to overcome an obstacle like this without having to rewrite large chunks of code.
在不必重写大量代码的情况下克服这样的障碍的最佳方法是什么?
采纳答案by Felix Kling
You can set dynamic keys is with bracket notation:
您可以设置动态密钥是用括号表示法:
required.directories[this.applicationPath + "/configs"] = "Application config folder does not exists";
(of course wherever you do this definition, this.applicationPath
must exist)
(当然,无论你做这个定义,this.applicationPath
必须存在)
But do you need this.applicationPath
in the keys? How do you access theses values? Maybe you can just remove this.applicationPath
from whatever value you use to access the properties.
但是你需要this.applicationPath
钥匙吗?您如何访问这些值?也许您可以this.applicationPath
从用于访问属性的任何值中删除。
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:
你可以使用一个数组初始化按键,如果你想避免重复大量的代码:
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
}
回答by Rich Apodaca
Computed property names are supported in ECMAScript2015:
ECMAScript2015 支持计算属性名称:
var name = 'key';
var value = 'value';
var o = {
[name]: value
};
alert("o as json : " + JSON.stringify(o));
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer
回答by RobG
In an object literal (ECMA-262 §11.1.5 calls it an "object initialiser") the key must be one of:
在对象字面量(ECMA-262 §11.1.5 称之为“对象初始化器”)中,键必须是以下之一:
- IdentifierName
- StringLiteral
- NumericLiteral
- 标识符名称
- 字符串字面量
- 数字文字
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:
所以你不能使用表达式作为初始化器中的键。您可以使用带有方括号表示法的表达式来访问属性。因此,要使用表达式设置属性,您必须执行以下操作:
var required = { directories : {}};
required.directories[this.applicationPath] = "Application " + this.application + " does not exists";
required.directories[this.applicationPath + "/configs"] = "Application config folder does not exists";
...
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:
等等。由于this.applicationPath
被大量重用,最好存储一个引用以帮助提高性能并减少代码量:
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";
...
Edit
编辑
As of ECMAScript ed 6, object initializers can have computed keys using:
从 ECMAScript ed 6 开始,对象初始值设定项可以使用以下方法计算键:
[expression]: value
There is also shorthand syntax for property and method names.
还有属性和方法名称的速记语法。
回答by Dan Barzilay
Inspired by how babelcoverts the new ES6 syntax ({[expression]: value}
) to old Javascript, I learned that you can do it with a one liner:
受到babel如何将新的 ES6 语法 ( {[expression]: value}
) 转换为旧的 Javascript 的启发,我了解到您可以使用单行代码来做到这一点:
var obj = (_obj = {}, _obj[expression] = value, _obj);
Example:
例子:
var dynamic_key = "hello";
var value = "world";
var obj = (_obj = {}, _obj[dynamic_key] = value, _obj);
console.log(obj);
// Object {hello: "world"}
(Tested on latest Chrome)
(在最新的 Chrome 上测试)
回答by DaveAlden
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:
如果您有一个深层的对象结构(例如 Grunt 配置),有时能够使用Felix概述的括号表示法返回动态生成的对象键会很方便,但在对象结构中内联。这可以通过使用一个函数在深层对象的上下文中动态返回一个对象来实现;在这个问题中的代码的情况下,是这样的:
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;
}()
}
This fiddlevalidates this approach.
这个小提琴验证了这种方法。
回答by user6451670
An old question, and the answers were correct at the time, but times change. In case someone digs it up in a google search, new javascript versions (ES6) allow using expressions as keys for object literals, if they are surrounded in square brackets:
var obj={["a"+Math.PI]:42}
一个古老的问题,当时的答案是正确的,但时代在变。如果有人在谷歌搜索中挖掘它,新的 javascript 版本 (ES6) 允许使用表达式作为对象文字的键,如果它们用方括号括起来:
var obj={["a"+Math.PI]:42}
回答by MooGoo
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.
对于对象字面量,Javascript/ECMAScript 脚本将键指定为有效的 IdentifierName、字符串字面量或数字信用 RobG(甚至十六进制)。不是一个表达,这是什么required.applicationPath + "/configs"
。
回答by japrescott
the problem is from using 'this' because it doesn't refer to anything smart*. create the static literal with the applicationPath in it.
问题在于使用“this”,因为它不涉及任何智能*。创建包含 applicationPath 的静态文字。
var required={ "applicationPath":"someWhereOverTheRainboW" };
Then use
然后使用
required.directories={}; required.directories[required.applicationPath + "/configs"]="Application config folder does not exists"; ....
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 ;)
*关键字'this'非常聪明:)但它通常指的是窗口对象或元素,事件已被触发或被调用的'活动'对象。因此,造成了很多混乱;)