2009-10-21 17 views
38

Ho letto che invece di scrivere semplicemente un po 'di funzioni, dovrei usare l'oggetto letterale.JavaScript - Vantaggi dell'oggetto letterale

Qualcuno può spiegare quali sono i vantaggi dell'oggetto letterale con gli esempi, perché non ho capito fino ad ora.

Grazie

risposta

64

Come ha detto Russ Cam, si evita di inquinare il namespace globale, che è molto importante in questi giorni di combinazione di script da più postazioni (TinyMCE, ecc).

Come ha detto Alex Sexton, rende anche buona organizzazione del codice.

Se si utilizza questa tecnica, suggerirei di utilizzare il modello del modulo. Questo utilizza ancora letterali oggetto, ma come valore restituito da una funzione di scoping:

var MyThingy = (function() { 

    function doSomethingCool() { 
     ... 
    } 

    function internalSomething() { 
     .... 
    } 

    function anotherNiftyThing() { 
     // Note that within the scoping function, functions can 
     // call each other direct. 
     doSomethingCool(); 
     internalSomething(); 
    } 

    return { 
     doSomethingCool: doSomethingCool, 
     anotherNiftyThing: anotherNiftyThing 
    }; 
})(); 

Uso esterno:

MyThingy.doSomethingCool(); 

La funzione di scoping è avvolto intorno a tutte le funzioni, e quindi si chiama subito e memorizza il suo valore di ritorno. Vantaggi:

  • funzioni sono dichiarate normalmente e quindi hanno nomi. (Mentre con il formato {name: function() { ... }}, tutte le funzioni sono anonime, anche se le proprietà che le fanno riferimento hanno nomi.) I nomi degli strumenti di aiuto aiutano a visualizzare quale stack di chiamate in un debugger ti dice quale funzione ha generato un'eccezione. (Aggiornamento 2015: l'ultima specifica JavaScript, ECMAScript 6a edizione, definisce un gran numero di modi in cui il motore JavaScript deve dedurre il nome di una funzione. Uno di questi è quando la funzione viene assegnata a una proprietà come nell'esempio {name: function() { ... }}. motori implementano ES6, questo motivo andrà via.)
  • Ti dà la libertà di avere funzioni private utilizzate solo dal tuo modulo (come il mio internalSomething sopra). Nessun altro codice sulla pagina può chiamare quelle funzioni; sono veramente privati. Solo quelli che esporti alla fine, nell'istruzione return, sono visibili al di fuori della funzione scoping.
  • Consente di restituire diverse funzioni in base all'ambiente, se l'implementazione cambia completamente (ad esempio materiale IE-vs-W3C o SVG o Canvas, ecc.).

Esempio di restituzione diverse funzioni:

var MyUtils = (function() { 
    function hookViaAttach(element, eventName, handler) { 
     element.attachEvent('on' + eventName, handler); 
    } 

    function hookViaListener(element, eventName, handler) { 
     element.addEventListener(eventName, handler, false); 
    } 

    return { 
     hook: window.attachEvent ? hookViaAttach : hookViaListener 
    }; 
})(); 

MyUtils.hook(document.getElementById('foo'), 'click', /* handler goes here */); 
+2

Quando installi una funzione in modo "anonimo", puoi comunque assegnargli un nome (var x = function x() {...}). Quando lo fai, il nome viene associato in modo tale che sia disponibile per i riferimenti ricorsivi all'interno della funzione. – Pointy

+1

@Pointy: non è possibile farlo (utilizzare un nome di funzione all'interno di un compito) cross-browser, non funziona correttamente su IE o Safari; dettagli: http://yura.thinkweb2.com/named-function-expressions/ E non è necessario, il nome proprio della funzione (il 'foo' in' function foo') è in-scope nell'intero ambito in cui è dichiarato, incluso all'interno della funzione stessa, quindi 'foo' può chiamarsi tramite il simbolo' foo', non è necessario assegnare il riferimento alla funzione a qualcosa (in quel punto). –

+0

(continua) Certo, sarebbe * bello * essere in grado di utilizzare contemporaneamente sia l'assegnazione sia il nome proprio perché renderebbe più semplice l'esportazione di funzioni dalla funzione di ambito. Lo spec certamente lo permette, ma purtroppo, praticità (bug di implementazione) entrano in esso. –

15

utilizzare un oggetto letterale (aka modello oggetto letterale) non inquinare il namespace globale così severamente come utilizzare molte funzioni dichiarate a livello globale sarà, e aiuta anche ad organizzare il codice in modo logico

Per esempio, questo oggetto letterale

var obj = { 
       find : function(elem) { /* find code */ }, 
       doSomething: function() { /* doSomething code */ }, 
       doSomethingElse: function() { /* doSomethingElse code */ } 
      } 

confrontato

function find(elem) { /* find code */ }, 
function doSomething() { /* doSomething code */ }, 
function doSomethingElse() { /* doSomethingElse code */ } 

creerà solo una proprietà sull'oggetto globale rispetto a tre. È quindi possibile utilizzare facilmente le funzioni in questo modo

obj.doSomething(); 
+2

potresti semplicemente scrivere molte funzioni in una funzione normale e non inquinare il tuo codice. l'oggetto letterale non fornisce alcun valore aggiunto. Io stesso uso il metodo prototipo .. – vsync

9

Rebecca Murphey ha fatto un discorso sul letterali oggetto alla conferenza jQuery di quest'anno. Uno dei migliori motivi per usarli è semplicemente una buona organizzazione del codice.

Ecco scrittura di Rebecca sul Motivo ornamentale Oggetto Letterale: http://rmurphey.com/blog/2009/10/15/using-objects-to-organize-your-code/

+2

Un altro grande articolo sui letterali degli oggetti: http://www.wait-till-i.com/2006/02/16/show-love-to-the-object-literal/ –

2

Ho sempre usato letterali oggetto perché sono un modo chiaro per organizzare codice. Ecco perché non mi piace il prototipo, è troppo disordinato.

Le funzioni non indicano lo spazio dei nomi come qualcuno menzionato sopra più di un oggetto letterale.

si potrebbe facilmente scrivere un letterale come

var obj = {} 
var find = function(elem) { /* find code */ }, 
var doSomething = function() { /* doSomething code */ }, 
var doSomethingElse = function() { /* doSomethingElse code */ } 

che inquinare con la creazione di un sacco di oggetti globali lo stesso lo stesso come le funzioni. Allo stesso modo si potrebbe fare:

(function() { 
function find(elem) { /* find code */ }, 
function doSomething() { /* doSomething code */ }, 
function doSomethingElse() { /* doSomethingElse code */ } 
})(); 

che non creerebbe quegli oggetti globali (tutto è un oggetto in JS)

in questo modo ancora non si crea carichi di oggetti globali.

A mio parere, gli oggetti letterali hanno due vantaggi. Uno sono utilizzati da molti plugin come jQuery, quindi le persone sono più familiari e sono facili da leggere. Rendendoli facili da passare attraverso i dati in un plugin. È facile creare metodi sia pubblici che privati ​​....

Possono essere lenti anche se ogni volta che si crea un'istanza dell'oggetto tutti i suoi metodi sono duplicati. Ho capito che non è il caso del prototipo in quanto si dispone di una copia dei metodi e i nuovi oggetti fanno semplicemente riferimento al prototipo.

Ovviamente potrei sbagliarmi ...

+1

I valori letterali degli oggetti sono validi per namespaces e singleton, quando si creano più istanze di un oggetto con comportamento condiviso, sarebbe meglio utilizzare le funzioni di costruzione. Non ho trovato un caso d'uso in cui consumare più CPU e memoria simulando i metodi privati ​​usando invece '_myPrivate' per i privati, ma sarei felice se qualcuno me ne potesse fornire uno. Maggiori informazioni su prototipo, ereditarietà, mix-in qui: http://stackoverflow.com/a/16063711/1641941 – HMR

Problemi correlati