Динамические клавиши для объектных литералов в Javascript
Хорошо, поэтому я работаю над проектом в 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"
}
}
Хорошо, поэтому многие из вас рассмотрят это и подумают, что это выглядит нормально, но компилятор продолжает говорить мне, что мне не хватает :
(двоеточие), что им не кажется, кажется, что +
или .
выполняются компилятором.
Теперь я верю (не уверен), что литералы объектов создаются во время компиляции, а не во время выполнения, что означает, что динамические переменные, такие как this.applicationPath
и конкатенация, не будут доступны:(: (
Какой лучший способ преодолеть такое препятствие, не переписывая большие куски кода.
Ответы
Ответ 1
Единственный способ, которым вы можете установить динамические клавиши, - это обозначение в виде скобок:
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
}
Ответ 2
В объектном литерале (ECMA-262 §11.1.5 называет его "инициализатором объекта" ), ключ должен быть одним из:
- ИмяИдентификатора
- СтроковойЛитерал
- ЧисловойЛитерал
Таким образом, вы не можете использовать выражение в качестве ключа в инициализаторе. Вы можете использовать выражение с квадратной скобкой для доступа к свойству. Поэтому, чтобы установить свойства с выражением, которое вы должны сделать:
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.
Ответ 3
Имена компьютерных объектов поддерживаются в ECMAScript2015:
var name = 'key';
var value = 'value';
var o = {
[name]: value
};
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer
Ответ 4
Вдохновленный тем, что 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)
Ответ 5
Для объектных литералов Javascript/ECMAScript script указывает ключи как действительное имя идентификатора, строковый литерал или число credit RobG (даже hex). Не выражение, которое есть required.applicationPath + "/configs"
.
Ответ 6
Если у вас есть глубокая структура объекта (например, Grunt config), иногда удобно возвращать динамически генерируемые ключи объектов, используя нотацию скобки, обозначенную 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;
}()
}
Эта скрипта подтверждает этот подход.
Ответ 7
Старый вопрос, и ответы были правильными в то время, но времена меняются. Если кто-то выкапывает его в поиске Google, новые версии javascript (ES6) позволяют использовать выражения как ключи для объектных литералов, если они окружены квадратными скобками:
var obj={["a"+Math.PI]:42}
Ответ 8
проблема заключается в использовании 'this', потому что он не ссылается ни на что умное *.
создайте статический литерал с помощью applicationPath в нем.
var required={
"applicationPath":"someWhereOverTheRainboW"
};
Затем используйте
required.directories={};
required.directories[required.applicationPath + "/configs"]="Application config folder does not exists";
....
чтобы заполнить его динамически
Изменить;
Я бросился своей первой идеей, это не сработало. Вышеупомянутые работы сейчас - извините за это!
* ключевое слово 'this' очень умное:), но оно часто относится к объекту окна или элементу, событию уволено или вызванному активному объекту. Таким образом, создавая много путаницы;)