chaves dinâmicas para literais de object em JavaScript

Ok, então estou trabalhando em um projeto nos Nós, e me deparei com um pequeno problema com as chaves em literais de object, tenho a seguinte configuração:

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, muitos de vocês vão olhar para isso e acho que está tudo bem, mas o compilador continua me dizendo que estou perdendo um : (cólon), o que não é, parece que o + ou + . ambos estão efetuando o compilador.

Agora eu acredito (não tenho certeza), que os literais de object são criados em tempo de compilation, e não em tempo de execução, o que significa que variables ​​dinâmicas como this.applicationPath e concatenação não estarão disponíveis 🙁 🙁

Qual é a melhor maneira de superar um obstáculo como esse sem ter que rewrite grandes blocos de código.

    A única maneira de definir chaves dinâmicas é com notação de colchetes:

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

    (claro que, onde quer que você faça essa definição, this.applicationPath deve existir)

    Mas você precisa this.applicationPath nas chaves? Como você acessa esses valores? Talvez você possa simplesmente remover this.applicationPath do valor que você usa para acessar as propriedades.


    Mas caso você precise disso:

    Você poderia usar uma matriz para inicializar as chaves se quiser evitar a repetição de vários códigos:

     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 } 

    Em um object literal (ECMA-262 §11.1.5 chama de “object inicializador”) a chave deve ser um dos seguintes:

    1. IdentifierName
    2. StringLiteral
    3. NuméricoLiteral

    Então você não pode usar uma expressão como a chave em um inicializador. Você pode usar uma expressão com notação de colchetes para acessar uma propriedade. Então, para definir as propriedades com uma expressão que você precisa fazer:

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

    e assim por diante. Como this.applicationPath é reutilizado muito, é melhor armazenar uma referência para ajudar no desempenho e reduzir a quantidade de código:

     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"; ... 

    Editar

    A partir do ECMAScript 6, os inicializadores de objects podem ter chaves calculadas usando:

     [expression]: value 

    Há também syntax abreviada para nomes de propriedades e methods.

    Veja MDN: Object Initializer ou ECMAScript §12.2.6 .

    Nomes de propriedades computadas são suportados no ECMAScript2015:

     var name = 'key'; var value = 'value'; var o = { [name]: value }; alert("o as json : " + JSON.stringify(o)); 

    Inspirado em como o babel cobre a nova syntax do ES6 ( {[expression]: value} ) para o Javascript antigo, aprendi que você pode fazer isso com um único liner:

     var obj = (_obj = {}, _obj[expression] = value, _obj); 

    Exemplo:

     var dynamic_key = "hello"; var value = "world"; var obj = (_obj = {}, _obj[dynamic_key] = value, _obj); console.log(obj); // Object {hello: "world"} 

    Para literais de object, o script Javascript / ECMAScript especifica chaves seja um IdentifierName válido, um literal de string ou um número de créditos RobG (até hexadecimal). Não é uma expressão, que é o que é required.applicationPath + "/configs" .

    Se você tem uma estrutura de object profunda (como a configuração do Grunt), às vezes é conveniente poder retornar chaves de object geradas dinamicamente usando a notação de colchetes descrita pelo Felix , mas embutida dentro da estrutura do object. Isso pode ser obtido usando uma function para retornar dinamicamente um object dentro do contexto do object profundo; no caso do código nesta pergunta, algo como isto:

     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; }() } 

    Este violino valida esta abordagem.

    Uma pergunta antiga e as respostas estavam corretas na época, mas os tempos mudam. No caso de alguém pesquisar em uma pesquisa no google, novas versões do javascript (ES6) permitem o uso de expressões como chaves para literais de object, se elas estiverem entre colchetes: var obj={["a"+Math.PI]:42}

    o problema é usar ‘isso’ porque não se refere a nada inteligente *. crie o literal estático com o applicationPath nele.

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

    Então use

     required.directories = {};
     required.directories [required.applicationPath + "/ configs"] = "A pasta de configuração do aplicativo não existe";
     ....
    

    preenchê-lo dinamicamente

    Editar; Corri com a minha primeira ideia, não funcionou. O acima funciona agora – desculpe por isso!

    * a palavra chave ‘this’ é muito inteligente 🙂 mas geralmente se refere ao object window ou ao elemento, o evento foi triggersdo ou o object ‘active’ chamado. Assim, criando muita confusão;)