динамические ключи для объектных литералов в Javascript
Итак, я работаю над проектом в узлах, и я столкнулся с небольшой проблемой с ключами в объектных литералах, у меня есть следующая настройка:
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"
}
}
хорошо, так что многие из вас будут смотреть на это и думать, что это выглядит нормально, но компилятор продолжает говорить мне, что мне не хватает :
(двоеточие), которого нет, похоже на +
или .
оба влияют на компилятор.
теперь я считаю (не уверен), что объектные литералы создаются при компиляции время, а не время выполнения, что означает, что динамические переменные, такие как this.applicationPath
и конкатенация не будет доступна : (: (
каков наилучший способ преодолеть такое препятствие без необходимости переписывать большие куски кода.
8 ответов:
единственный способ, которым вы можете установить динамические клавиши, - это скобочная нотация:
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
- StringLiteral
- 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"; ...
и так далее. Так как
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
начиная с ECMAScript ed 6, инициализаторы объектов могут иметь вычисленные ключи, используя:
[expression]: value
существует также сокращенный синтаксис для имен свойств и методов.
посмотреть MDN: инициализатор объекта или ECMAScript §12.2.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
вдохновленный как Бабель скрывает новый синтаксис 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)
для объектных литералов сценарий Javascript/ECMAScript указывает, что ключи должны быть либо допустимым IdentifierName, строковым литералом, либо числом кредит RobG (даже hex). Не выражение, а что такое
required.applicationPath + "/configs"
есть.
Если у вас есть глубокая структура объекта (например, Grunt config), иногда удобно возвращать динамически сгенерированные ключи объектов, используя скобочную нотацию, обозначенную Феликс, но встроенный в структуру объекта. Это может быть достигнуто с помощью функции для динамического возврата объекта в контексте глубокого объекта; в случае кода в этом вопросе, что-то вроде этого:
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; }() }
эта скрипка проверяет это подход.
старый вопрос, и ответы были правильными в свое время, но времена меняются. В случае, если кто-то выкопает его в поиске google, новые версии javascript (ES6) позволяют использовать выражения в качестве ключей для объектных литералов, если они заключены в квадратные скобки:
var obj={["a"+Math.PI]:42}
проблема заключается в использовании "это", потому что это не относится ни к чему умному*. создайте статический литерал с applicationPath в нем.
var required={ "applicationPath":"someWhereOverTheRainboW" };затем использовать
required.directories={}; required.directories[required.applicationPath + "/configs"]="Application config folder does not exists"; ....заполнить его динамически
изменить; Я поспешил с моей первой идеей, она не сработала. Выше работает сейчас-извините за это!
* ключевое слово 'это' очень умный :) но это часто относится к объекту окна или элементу, событие было запущено или вызванный "активный" объект. Таким образом, создавая много путаницы ;)