динамические ключи для литералов объекта в Javascript - PullRequest
73 голосов
/ 28 июня 2011

Хорошо, так что я работаю над проектом в 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"
    }
}

Okтак многие из вас посмотрят на это и подумают, что все в порядке, но компилятор постоянно говорит мне, что я пропускаю : (двоеточие), а это не так, похоже, что + или .оба влияют на компилятор.

Теперь я верю (не уверен), что литералы объектов создаются во время компиляции, а не во время выполнения, то есть динамические переменные, такие как this.applicationPath и конкатенация, не будутдоступно :(: (

Какой лучший способ преодолеть подобное препятствие без необходимости переписывать большие куски кода.

Ответы [ 8 ]

87 голосов
/ 28 июня 2011

В литерале объекта (ECMA-262 §11.1.5 называет его «инициализатором объекта») ключ должен быть одним из:

  1. ИмяИдентификатор
  2. СтроковойЛитерал
  3. ЧисловойЛитерал

Таким образом, вы не можете использовать выражение в качестве ключа в инициализаторе. Вы можете использовать выражение в квадратных скобках для доступа к свойству. Итак, чтобы установить свойства с выражением, вы должны сделать:

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 .

81 голосов
/ 04 августа 2016

Вычисляемые имена свойств поддерживаются в 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

40 голосов
/ 28 июня 2011

Единственный способ установить динамические клавиши - с помощью скобок:

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
}
5 голосов
/ 28 февраля 2016

Вдохновленный тем, как 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)

2 голосов
/ 10 июня 2016

Старый вопрос, и ответы были правильными в то время, но времена меняются. В случае, если кто-то найдет его в поиске Google, новые версии javascript (ES6) позволяют использовать выражения в качестве ключей для литералов объекта, если они заключены в квадратные скобки: var obj={["a"+Math.PI]:42}

2 голосов
/ 18 декабря 2014

Если у вас глубокая объектная структура (например, конфигурация Grunt), иногда удобно иметь возможность возвращать динамически сгенерированные ключи объекта, используя обозначение в скобках, обозначенное 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;
    }()
}

Эта скрипка подтверждает этот подход.

2 голосов
/ 28 июня 2011

Для объектных литералов сценарий Javascript / ECMAScript указывает, что ключом может быть либо действительный идентификатор, строковый литерал, либо число кредит RobG (даже шестнадцатеричный).Не выражение, которым является required.applicationPath + "/configs".

0 голосов
/ 28 июня 2011

проблема заключается в использовании 'this', потому что оно не относится к чему-либо умному *.создайте статический литерал с applicationPath в нем.

var required={
    "applicationPath":"someWhereOverTheRainboW"
};

Затем используйте

required.directories={};
required.directories[required.applicationPath + "/configs"]="Application config folder does not exists";
....

, чтобы заполнить его динамически

Редактировать;Я бросился с моей первой идеей, она не сработала.Выше работает сейчас - извините за это!

* ключевое слово 'this' очень умное:) но оно часто относится к объекту окна или элементу, по которому было инициировано событие, или к вызываемому активному объекту.Таким образом, создавая много путаницы;)

...