динамические ключи для объектных литералов в 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 называет его "инициализатором объекта") ключ должен быть одним из:

  1. IdentifierName
  2. StringLiteral
  3. 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" очень умное:) но это часто относится к объекту окна или элементу, событие было запущено на или вызываемый "активный" объект. Таким образом, создавая много путаницы ;)