Javascript 中对象文字的动态键 [duplicate]

dynamic keys for object literals in Javascript [duplicate]

提问人:RobertPitt 提问时间:6/28/2011 最后编辑:Jonathan LefflerRobertPitt 更新时间:10/16/2020 访问量:58157

问:

好的,所以我正在 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"
    }
}

好的,你们中的很多人会看这个并认为它看起来没问题,但是编译器一直告诉我我缺少一个(冒号),而事实并非如此,似乎 or 和 the 都在影响编译器。:+.

现在我相信(不确定),对象文字是在编译时创建的,而不是在运行时创建的,这意味着动态变量(如和串联)将:( :(不可用this.applicationPath

克服这样的障碍而不必重写大量代码的最佳方法是什么?

JavaScript 对象文字

评论

0赞 vorburger 7/25/2013
你可能会发现我有点相关的 stackoverflow.com/questions/17841915/......对这个背景感兴趣。
0赞 OneHoopyFrood 10/12/2019
现在可能被骗了吗?stackoverflow.com/a/19837961/1795429

答:

0赞 japrescott 6/28/2011 #1

问题在于使用“this”,因为它不是指任何智能*。 创建包含 applicationPath 的静态文本。

var required={
    "applicationPath":"someWhereOverTheRainboW"
};

然后使用

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

动态填充

编辑; 我匆匆忙忙地提出了我的第一个想法,但没有奏效。以上现在有效 - 对不起!

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

评论

0赞 RobertPitt 6/28/2011
您能否举例说明您的意思是,我刚刚尝试的方式仍然会抛出错误?
0赞 japrescott 6/28/2011
添加了您想要的缺失行
0赞 RobertPitt 6/28/2011
感谢您的更新,这就是我假设您的意思,但是当涉及到键时,我仍然遇到错误,抛出的错误是 语法错误:意外令牌 。
2赞 MooGoo 6/28/2011 #2

对于对象文字,Javascript/ECMAScript 脚本将键指定为有效的 IdentifierName、字符串文字或数字信用 RobG(甚至十六进制)。不是表达式,这就是。required.applicationPath + "/configs"

评论

0赞 RobertPitt 6/28/2011
不算作有效标识符?this.applicationPath
0赞 MooGoo 6/28/2011
也是一个表达式,因为 的值在运行时之前是未知的。this
0赞 RobG 6/28/2011
罗伯特皮特 - 不,这是一种表达方式。
0赞 RobG 6/28/2011
请注意,键可以是 IdentifierName,这与标识符不同。如果使用与标识符同名的键(例如变量名称),则它会创建具有该名称的属性,它不会解析标识符并使用标识符的值创建属性(否则它将被视为表达式,而它不能)。
46赞 Felix Kling 6/28/2011 #3

您可以使用括号表示法设置动态键:

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

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

但是你需要钥匙吗?如何访问这些值?也许你可以从你用来访问属性的任何值中删除。this.applicationPaththis.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
}

评论

0赞 RobertPitt 6/28/2011
我不需要它们在钥匙中,但这只是一个偏好,改变它,你的方法似乎是最合理的。
0赞 RobertPitt 6/28/2011
谢谢 Felix,我选择了“/config”方法作为键,并在 for 循环中连接,我没有理由在索引中使用变量,但这里已经很晚了,再次感谢萌芽。
2赞 JLRishe 11/20/2017
我认为这个答案需要更新以提及计算属性名称
0赞 bucabay 7/2/2019
虽然很冗长,但您可以使用: ,其中 key 和 value 是变量,通过定义具有该键和值的对象,以文字对象表示法分布到其中。虽然在支持的地方会很简洁。{ ...Object.defineProperty({}, key, { value, enumerable: true }) }{ [key]: value }
111赞 RobG 6/28/2011 #4

在 ECMAScript 2015 (ed 6) 之前,对象字面量(ECMAScript 称其为“对象初始值设定项”)键必须是以下项之一:

  1. 标识符名称
  2. StringLiteral(字符串文字)
  3. NumericLiteral

因此,您不能将表达式用作初始值设定项中的键。自 ECMAScript 2015 起,此情况已更改(见下文)。您可以使用带有方括号表示法的表达式来访问属性,因此要使用表达式设置属性,您必须执行以下操作:

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

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 2015 (ed 6) 开始,对象初始值设定项可以使用以下命令计算键:

[expression]: value

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

参见 MDN:对象初始值设定项或 ECMAScript 对象初始值设定项

评论

9赞 Ciro Santilli OurBigBook.com 6/16/2014
因为你引用了标准,以及确切地说,什么可以用作关键。
0赞 Lee Goddard 5/10/2017
ECMA成为USCMA....?
0赞 Antonis Christofides 8/23/2017
“初始值设定项”不是以美国为中心的;请参阅 quora.com/...
0赞 RobG 8/24/2017
@AntonisChristofides - 它是英语的美国变体所采用的拼写。
0赞 Antonis Christofides 8/24/2017
@RobG 它被美国采用,但不是以美国为中心。它在英国也被使用;取决于你是去牛津还是剑桥。-izer 拼写早于 US。您可以在我在之前的评论中发布的链接中找到更多信息。
3赞 DaveAlden 12/18/2014 #5

如果你有一个深层的对象结构(比如 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;
    }()
}

这把小提琴验证了这种方法。

8赞 Dan Barzilay 2/29/2016 #6

受到 babel 如何将新的 ES6 语法 () 转换为旧 Javascript 的启发,我了解到你可以用一句话来做到这一点:{[expression]: value}

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

(在最新的 Chrome 上测试)

3赞 user6451670 6/11/2016 #7

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

221赞 Rich Apodaca 8/5/2016 #8

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

评论

26赞 Gershom Maes 1/12/2017
随着时间的流逝,这已成为最正确的答案!
3赞 orion elenzil 3/22/2019
事实上!你能@RobertPitt改变公认的答案吗?
0赞 yuceel 11/7/2019
哇。这对我来说是一件新鲜事。完善。“计算属性名称”,用于该概念。
1赞 Daniel Brady 12/17/2019
这是一个更正确的答案,从某种意义上说,它比公认的答案更好地回答了被问到的问题:接受的答案处理的是绑定对象,而不是对象文字/“内联对象”。
0赞 Preom 4/11/2021
我记得几年前看到这个,认为这是不必要的。它实际上对 Typescript 非常有用,因为它在对象创建时隐式推断类型并保存了大量丑陋的、显式的样板代码。