Javascript中对象文字的动态键

Rob*_*itt 80 javascript object-literal

好吧,我正在努力开发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"
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,你们很多人都会看到它并认为它看起来没问题,但是编译器一直告诉我,我错过了一个:(冒号),我不是,它看起来像+或者.都在影响编译器.

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

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

Rob*_*obG 95

在对象文字中(ECMA-262§11.1.5称之为"对象初始化"),密钥必须是以下之一:

  1. IdentifierName
  2. 字符串字面量
  3. NumericLiteral

因此,您不能将表达式用作初始化器中的键.您可以使用带方括号表示法的表达式来访问属性.因此,要使用您必须执行的表达式设置属性:

var required = { directories : {}};
required.directories[this.applicationPath] = "Application " + this.application + " does not exists";
required.directories[this.applicationPath + "/configs"] = "Application config folder does not exists";
...
Run Code Online (Sandbox Code Playgroud)

等等.由于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";
...
Run Code Online (Sandbox Code Playgroud)

编辑

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

[expression]: value
Run Code Online (Sandbox Code Playgroud)

属性和方法名称也有简写语法.

请参阅MDN:对象初始化程序ECMAScript§12.2.6.

  • Upvote是因为您引用了标准,并且确切地说可以用作关键字. (8认同)

Ric*_*aca 94

ECMAScript2015支持计算属性名称:

var name = 'key';
var value = 'value';
var o = {
  [name]: value
};
alert("o as json : " + JSON.stringify(o));
Run Code Online (Sandbox Code Playgroud)

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

  • 随着时间的推移,这已成为最正确的答案! (16认同)
  • 确实!@RobertPitt您可以更改接受的答案吗? (2认同)

Fel*_*ing 41

设置动态键的唯一方法是使用括号表示法:

required.directories[this.applicationPath + "/configs"] = "Application config folder does not exists";
Run Code Online (Sandbox Code Playgroud)

(当然,无论你做什么定义,都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
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为此答案需要更新以提及[计算的属性名称](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names)。 (2认同)

Dan*_*lay 6

受到babel如何将新的ES6语法({[expression]: value})转换为旧Javascript的启发,我了解到你可以用一个内容来实现:

var obj = (_obj = {}, _obj[expression] = value, _obj);
Run Code Online (Sandbox Code Playgroud)

例:

var dynamic_key = "hello";
var value = "world";
var obj = (_obj = {}, _obj[dynamic_key] = value, _obj);

console.log(obj);
// Object {hello: "world"}
Run Code Online (Sandbox Code Playgroud)

(在最新的Chrome上测试过)