Динамические клавиши для объектных литералов в 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.

Ответ 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' очень умное:), но оно часто относится к объекту окна или элементу, событию уволено или вызванному активному объекту. Таким образом, создавая много путаницы;)