Javascript中对象文字的动态键

IT技术 javascript object-literal
2021-01-29 04:14:36

好的,所以我正在 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和 连接)将不可用:( :(

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

6个回答

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

我记得几年前看到这个并认为这是不必要的。它实际上对 Typescript 非常有用,因为它隐式地推断对象创建时的类型并节省了大量丑陋、显式的样板代码。
2021-03-23 04:14:36
这是一个更正确的答案,因为它回答了比接受的答案更好的问题:接受的答案处理绑定对象,而不是对象文字/“内联对象”。
2021-03-25 04:14:36
随着时间的推移,这已成为最正确的答案!
2021-04-08 04:14:36
哇。这对我来说是一件新鲜事。完美的。“计算属性名称”,感谢这个概念。
2021-04-08 04:14:36
的确!@RobertPitt 你能改变这个接受的答案吗?
2021-04-09 04:14:36

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

  1. 标识符名称
  2. 字符串字面量
  3. 数字文字

所以你不能使用表达式作为初始化器中的键。这在 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 对象初始化程序

ECMA 变成 USCMA ......?
2021-03-13 04:14:36
赞成,因为您引用了标准,以及可以用作关键的内容。
2021-03-24 04:14:36
“初始化程序”不是以美国为中心的;quora.com/…
2021-03-25 04:14:36
@RobG 它美国采用,但不是以美国为中心。它也在英国使用;取决于你是去牛津还是剑桥。-izer 拼写早于美国。您可以在我在之前的评论中发布的链接中找到更多信息。
2021-04-02 04:14:36
@AntonisChristofides——这是美国英语变体采用的拼写。
2021-04-09 04:14:36

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

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
}
尽管冗长,您可以使用:{ ...Object.defineProperty({}, key, { value, enumerable: true }) },其中键和值是通过定义具有该键和值的对象以文字对象表示法传播的变量。虽然{ [key]: value }在支持的情况下会简洁。
2021-03-12 04:14:36
我认为这个答案需要更新以提及计算属性名称
2021-03-18 04:14:36
不需要它们在钥匙中,但这只是一种偏好,很难改变它,你的方法似乎最合理。
2021-03-23 04:14:36
谢谢 Felix,我选择了“/config”方法作为关键,并在 for 循环中连接,我没有理由使用索引中的变量,但这里已经晚了,再次感谢 bud。
2021-03-25 04:14:36

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

(在最新的 Chrome 上测试)

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

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