динамические ключи для объектных литералов в 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
таким образом, вы не можете использовать выражение в качестве ключа в инициализаторе. Для доступа к свойству можно использовать выражение с квадратной скобкой. Поэтому, чтобы установить свойства с выражением, вы должны 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";
...
и так далее. С 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 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 указывает, что ключи должны быть допустимым Identifierame, строковым литералом или числом кредит RobG (даже hex). Не выражение, а то, что required.applicationPath + "/configs"
есть.
Если у вас есть глубокая структура объекта (например, конфигурация Grunt), иногда удобно иметь возможность возвращать динамически сгенерированные ключи объекта, используя скобочную нотацию, описанную Феликс, но встроенный в структуру объекта. Это может быть достигнуто с помощью функции для динамического возврата объекта в контексте глубокого объекта; в случае кода в этом вопросе что-то вроде этого:
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"; ....
заполнить его динамически
изменить; Я поспешил с моей первой идеей, она не сработала. Вышеизложенное работает сейчас-извините за это!
* ключевое слово "this" очень умное:) но это часто относится к объекту окна или элементу, событие было запущено на или вызываемый "активный" объект. Таким образом, создавая много путаницы ;)