2013-02-20 18 views
39

L'enumerabilità è uno dei tre attributi di una proprietà: scrivibilità, enumerabilità e configurabilità. Le mie domande sono:Quali sono i vantaggi di rendere le proprietà non enumerabili?

  • Quali sono i vantaggi di rendere le proprietà non enumerabili in JavaScript? So che stiamo nascondendo la proprietà rendendoli non enumerabili, ma quali sono i vantaggi della proprietà nascosta?
  • Possiamo accedere a proprietà non enumerabili? Se sì, allora qual è il vantaggio di renderli non enumerabili?
  • Tutte le proprietà predefinite degli oggetti sono impostate come non enumerabili? Ad esempio il caso delle proprietà pop e push di Array non è enumerabile?
+1

Credo che il vantaggio principale è quello di rendere 'per tale dicitura loop di sicurezza - la proprietà non verrà mostrata quando l'iterazione sopra l'oggetto. Forse sto dimenticando cosa fa l'enumerabilità ... – Ian

+2

Correlati: [Quali sono i vantaggi e i pericoli dell'aggiunta di metodi a Object.prototype in Javascript?] (Http://stackoverflow.com/questions/3832617/what-are-the -benefici-e-pericoli-di-aggiunta-metodi-to-oggetto-prototipo-in-Javas? RQ = 1). –

risposta

35

Credo che il vantaggio principale è quello di essere in grado per controllare cosa viene visualizzato quando si enumerano le proprietà di un oggetto, ad esempio for in o Object.keys().

MDN spiega bene con Object.defineProperty: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty

così normalmente, quando la gente vuole aggiungere un metodo per Object, come ad esempio un polyfill per qualche metodo non supportato in vecchi browser, essi modificano il .prototype. Ma questo rende la proprietà enumerabile e incasella ciò che viene restituito nella raccolta loop/chiavi (senza usare .hasOwnProperty ... che non tutti usano).

Così, invece di qualcosa come:

Object.prototype.myMethod = function() { 
    alert("Ahh"); 
}; 

si potrebbe usare Object.defineProperty dire in modo esplicito per averlo non essere enumerabile:

Object.defineProperty(Object.prototype, 'myMethod', { 
    value: function() { 
     alert("Ahh"); 
    }, 
    enumerable: false 
}); 

In questo modo, per esempio quando si utilizza for (var key in obj), "myMethod "non sarà un elemento elencato e non dovrai preoccuparti di utilizzare .hasOwnProperty. Il problema principale con questo è che alcuni browser non lo supportano ovviamente: http://kangax.github.com/es5-compat-table/ e che non tutte le librerie/il codice lo usano, quindi non si può sempre fare affidamento su librerie esterne/codice per fare un uso corretto e sempre.

È possibile accedere a una proprietà non enumerabile in qualsiasi momento, ma non verrà visualizzato quando si enumerano le proprietà dell'oggetto: questo è il punto principale.

E credo che tutte le proprietà "predefinite" degli oggetti non siano enumerabili. Con ciò intendo solo proprietà native, non necessariamente ereditate o create. Quindi con il tuo esempio, pop e push sarà non essere enumerato, ma Array.prototype.indexOf sarà se è stato creato come un polyfill su un vecchio browser che non supporta tale metodo ...che, naturalmente, può essere evitato usando Object.defineProperty come il mio esempio sopra. Un altro esempio è la proprietà length, che non viene enumerata.

Ecco un esempio in generale: http://jsfiddle.net/aHJ3g/

L'uso e la definizione di Object.keys è importante: "restituisce un array di proprie proprietà enumerabili di un determinato oggetto, nello stesso ordine di quella fornita da un anello for-in (la differenza dal momento che un ciclo for-in enumera anche le proprietà nella catena del prototipo. " - da MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys

2
  • Rendendo la proprietà non enumerabile è ancora possibile accedervi. Ma quando si applica a for in loop sull'oggetto la proprietà non enumerabile non verrà iterata.
  • Vedi primo punto
  • proprietà ereditate di oggetti incorporati (come push, pop, toString ...) non sono enumerabili

    var o = {a:1, b:2, c:3} // a,b,c are enumerable properties 
    o.propertyIsEnumerable("toString") // returns false, because it is a inherited property 
    for(p in o) console.log(p); // this loop will print a,b and c but not toString or other inherited properies 
    
+2

Credo che il terzo punto sia sbagliato. Le proprietà ereditate sono certamente enumerabili come tutte le altre ... 'var x = {a: 1}; var y = Object.create (x); y.b = 2; for (name in y) {console.log (name, y [nome]);} 'produce' b 2' e 'a 1'. –

+0

Hai ragione! Anche le proprietà ereditate sono enumerabili. Se si desidera solo proprietà proprie ed enumerabili, utilizzare Object.keys(). – daniatic

11

Un altro vantaggio importante, a quanto vedo, è che impedisce alle proprietà private di un oggetto di inquinare lo spazio dei nomi pubblico.

Supponiamo di aver creato e pubblicato una potente libreria denominata Cosmos. L'utente spara l'interprete Node e crea una nuova istanza di esso chiamando il costruttore:

var Cosmos = require('Cosmos'); 
var cosmos = new Cosmos('my empire'); 

Ora l'utente semplicemente tipi cosmos e preme Invio per vedere quali API pubblica che supporta. Quale dei due vuoi che l'utente veda?

{ name: 'my empire', 
    grow: [Function: grow], 
    addStar: [Function: addStar], 
    beautify: [Function: beautify], 
    implode: [Function: implode], 
    destroy: [Function: destroy] } 

O

{ _age: 25000, 
    _size: 35000, 
    _destroyed: false, 
    name: 'my empire', 
    _numStars: 200, 
    _init: [Function: _init], 
    grow: [Function: grow], 
    _grow: [Function: _grow], 
    addStar: [Function: addStar], 
    _checkStatus: [Function: _checkStatus], 
    beautify: [Function: beautify], 
    implode: [Function: implode], 
    destroy: [Function: destroy] } 
+3

le proprietà non enumerabili sono ancora pubbliche e continuano a inquinare lo spazio dei nomi. Se vuoi proprietà private, hai bisogno di una chiusura. – Matthew

+4

Ho svalutato sia la risposta che il commento critico. La critica del commento mi sembra valida, quindi forse l'uso del rispondente di "pubblico" e "privato" potrebbe non essere ottimale. Tuttavia, ritengo che il punto della risposta sia ancora utile (almeno lo è stato per me) perché mostra come l'enumerabilità può aiutare l'utente della biblioteca a vedere più facilmente ciò che l'autore della libreria è destinato all'utente della biblioteca (ad es. grow' e non '_grow', anche se entrambi sono ancora tecnicamente pubblici). –

Problemi correlati