tasti dinamici per oggetti letterali in Javascript

Ok, quindi sto lavorando su un progetto in Nodi e ho riscontrato un piccolo problema con le chiavi in ​​oggetti letterali, ho il seguente set-up:

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, molti di voi guarderanno questo e penseranno che sia OK, ma il compilatore continua a dirmi che mi manca un : (due punti), che non lo sono, sembra come il + o e il . stanno entrambi effettuando il compilatore.

Ora credo (non sono sicuro) che i letterali dell’object siano creati in fase di compilazione e non in fase di esecuzione, il che significa che le variabili dinamiche come this.applicationPath e la concatenazione non saranno disponibili 🙁 🙁

Qual è il modo migliore per superare un ostacolo come questo senza dover riscrivere grossi pezzi di codice.

    L’unico modo per impostare le chiavi dinamiche è con la notazione delle parentesi:

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

    (Ovviamente ovunque si faccia questa definizione, this.applicationPath deve esistere)

    Ma hai bisogno di this.applicationPath nelle chiavi? Come si accede a questi valori? Forse puoi semplicemente rimuovere this.applicationPath da qualsiasi valore tu usi per accedere alle proprietà.


    Ma nel caso tu ne abbia bisogno:

    È ansible utilizzare un array per inizializzare i tasti se si desidera evitare di ripetere un sacco di codice:

     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 } 

    In un object letterale (ECMA-262 §11.1.5 lo chiama “inizializzatore dell’object”) la chiave deve essere una delle seguenti:

    1. IdentifierName
    2. letterale stringa
    3. NumericLiteral

    Quindi non puoi usare un’espressione come chiave in un inizializzatore. È ansible utilizzare un’espressione con notazione a parentesi quadre per accedere a una proprietà. Quindi, per impostare le proprietà con un’espressione che devi fare:

     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 così via. Poiché this.applicationPath viene riutilizzato molto, è meglio memorizzare un riferimento per aiutare con le prestazioni e ridurre la quantità di codice:

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

    modificare

    A partire da ECMAScript ed 6, gli inizializzatori di oggetti possono avere chiavi calcolate usando:

     [expression]: value 

    C’è anche syntax abbreviata per nomi di proprietà e metodi.

    Vedere MDN: Object Initializer o ECMAScript §12.2.6 .

    I nomi delle proprietà calcolate sono supportati in ECMAScript2015:

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

    Ispirato da come babel ricopre la nuova syntax ES6 ( {[expression]: value} ) in vecchio Javascript, ho imparato che puoi farlo con un solo liner:

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

    Esempio:

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

    Per gli oggetti letterali, lo script Javascript / ECMAScript specifica che le chiavi possono essere un IdentifierName valido, un letterale stringa o un RobG di credito numerico (esadecimale pari). Non è un’espressione, che è quanto required.applicationPath + "/configs" è.

    Se si dispone di una struttura di oggetti profonda (come Grunt config), è a volte conveniente poter restituire chiavi di oggetti generate dynamicmente usando la notazione della parentesi delineata da Felix , ma in linea all’interno della struttura dell’object. Questo può essere ottenuto usando una funzione per restituire dynamicmente un object all’interno del contesto dell’object profondo; nel caso del codice in questa domanda, qualcosa del genere:

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

    Questo violino convalida questo approccio.

    Una vecchia domanda e le risposte erano corrette al momento, ma i tempi cambiano. Nel caso qualcuno lo scavi in ​​una ricerca su google, le nuove versioni javascript (ES6) consentono di utilizzare espressioni come chiavi per i letterali degli oggetti, se sono racchiuse tra parentesi quadre: var obj={["a"+Math.PI]:42}

    il problema è usare ‘questo’ perché non si riferisce a nulla di intelligente *. crea il letterale statico con applicationPath in esso.

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

    Quindi utilizzare

     required.directories = {};
     required.directories [required.applicationPath + "/ configs"] = "La cartella di configurazione dell'applicazione non esiste";
     ....
    

    per riempirlo dynamicmente

    Modificare; Mi sono precipitato con la mia prima idea, non ha funzionato. Quanto sopra funziona ora – mi dispiace per quello!

    * la parola chiave ‘this’ è molto intelligente 🙂 ma si riferisce spesso all’object window o all’elemento, l’evento è stato triggersto o l’object chiamato ‘active’. Quindi, creando molta confusione;)