Differenza tra congelamento e sigillo


164

Ho appena sentito parlare dei metodi JavaScript freezee seal, che possono essere utilizzati per rendere immutabile qualsiasi oggetto.

Ecco un breve esempio su come usarlo:

var o1 = {}, o2 = {};
Object.freeze(o2);

o1["a"] = "worked";
o2["a"] = "worked";

alert(o1["a"]);   //prints "worked"
alert(o2["a"]);   //prints "undefined"

Qual è la differenza tra freezee seal? Possono aumentare le prestazioni?


6
Solo una nota per chiunque guardi a questa domanda, la risposta accettata è effettivamente errata. La risposta di @ tungd è corretta.
Bjorn,

2
Un'altra nota, c'è anche Object.preventExtensionsin aggiunta a Object.seale Object.freeze. Object.preventExtensionsimpedisce solo che nuovi oggetti vengano aggiunti a un oggetto. È possibile eliminare, configurare e modificare i valori delle proprietà sugli oggetti per i quali è stata disattivata la loro estensibilità Object.preventExtensions.
Bjorn,

Risposte:


193

Object.seal

  • Impedisce l'aggiunta e / o la rimozione di proprietà dall'oggetto sigillato; l'utilizzo deleterestituirà false
  • Rende non configurabili tutte le proprietà esistenti : non possono essere convertite da "descrittori di dati" in "descrittori di accessori" (e viceversa) e nessun attributo di descrittori di accessori può essere modificato affatto (mentre i descrittori di dati possono cambiare il loro writableattributo e il loro valueattributo se writeableè vero).
  • Può lanciare un TypeErrortentativo di modificare il valore dell'oggetto sigillato stesso (più comunemente in modalità rigorosa )

Object.freeze

  • Esattamente cosa Object.sealfa, oltre a:
  • Impedisce di modificare qualsiasi proprietà esistente

Nessuno dei due influisce su oggetti "profondi" / nipoti. Ad esempio, se objè bloccato, obj.elnon può essere riassegnato, ma il valore di obj.elpotrebbe essere modificato, ad esempio obj.el.idpuò essere modificato.


Prestazione:

Sigillare o congelare un oggetto può influire sulla sua velocità di enumerazione, a seconda del browser:

  • Firefox: le prestazioni di enumerazione non sono influenzate
  • IE: l'impatto sulle prestazioni dell'enumerazione è trascurabile
  • Chrome: le prestazioni di enumerazione sono più veloci con oggetti sigillati o congelati
  • Safari: gli oggetti sigillati o congelati sono più lenti del 92% (a partire dal 2014)

Test: oggetti sigillati , oggetti congelati .


2
Puoi parlarci del motivo per cui dovremmo mai usare questi metodi? Solo perché possiamo?
Alan Dong,

3
In futuro penso che verranno usati molto (se ottimizzati correttamente) quando si sviluppa una libreria / framework. Consentono di impedire all'utente di rompere (anche involontariamente) il codice (e, come indicato nella risposta, le ottimizzazioni dovrebbero portare a grandi miglioramenti della velocità). Ma questa è pura speculazione :)
Niccolò Campolungo,

2
Questa risposta ha molti errori concreti. Per uno, sealrende anche le proprietà esistenti non configurabili, vedi jsfiddle.net/btipling/6m743whn numero 2, è ancora possibile modificare, ovvero cambiare i valori delle proprietà esistenti su un oggetto sigillato.
Bjorn,

8
FWIW, gli oggetti congelati e sigillati sono ora più veloci delle loro controparti non congelate e non sigillate in Chrome Canary v43.0.2317.0.
llambda,

2
@AlanDong Un po 'in ritardo, ma ecco perché vuoi bloccare un oggetto. Una delle caratteristiche di JavaScript è che puoi aggiungere una proprietà ogni volta che vuoi; puoi anche farlo accidentalmente digitando male. Molti dei miei studenti hanno provato ad aggiungere un gestore di eventi chiamato onClicko onlicke si chiedevano perché non funzionasse. Se JavaScript genera un errore, questa è un'altra cosa da sbagliare. In secondo luogo, ciò consente di implementare proprietà costanti su un oggetto che impedisce le modifiche. Ciò è particolarmente utile per i methjod degli oggetti.
Manngo,

119

Ho scritto un progetto di prova che confronta questi 3 metodi:

  • Object.freeze()
  • Object.seal()
  • Object.preventExtensions()

I miei test unitari riguardano casi CRUD:

  • [C] aggiungi nuova proprietà
  • [R] leggi proprietà esistente
  • [U] modifica proprietà esistente
  • [D] rimuove la proprietà esistente

Risultato:

inserisci qui la descrizione dell'immagine


2
È brillante. UPDATE tiene conto della modifica (tramite defineProperty) degli attributi del descrittore, ad esempio configurabile, enumerabile, scrivibile?
Drenai,

Ho sempre pensato che gli oggetti DOM dovrebbero essere sigillati (dopo i polifillamenti, ovviamente). Ciò contribuirebbe a prevenire molti errori di battitura.
Manngo,

@Manngo Puoi sigillare i tuoi oggetti DOM. Basta creare una DEBUGMODEvariabile e impostarla su true. Quindi, fallo if (DEBUGMODE) { ... }. Nel ..., inserisci la tua funzionalità per garantire che tutti gli oggetti DOM siano sempre sigillati. Quindi, quando si è pronti per distribuire lo script della pagina Web, passare DEBUGMODEa false, eseguire lo script tramite il compilatore di chiusura e distribuirlo. E 'così semplice.
Jack Giffin,

@JackGiffin Grazie per il commento. Stavo solo dicendo che ho sempre pensato che sarebbe stata una buona idea. Ho molti studenti che finiscono per scrivere qualcosa di simile element.onlick=somethinge si sentono frustrati perché non funziona, ma tecnicamente non è un errore.
Manngo,

2
@Lonely Quindi non scriverebbe CRUD. Dovresti accontentarti di qualcosa come RUDE;)
Manngo,

84

Puoi sempre cercarli in MDN. In breve:

  • Congela : rende l'oggetto immutabile, il che significa che non sono consentite modifiche alla proprietà definita, a meno che non siano oggetti.
  • Sigillo : impedisce l'aggiunta di proprietà, tuttavia le proprietà definite possono ancora essere modificate.

1
Object.seal()sembra anche congelare le proprietà del prototipo: \
K ..

10

Object.freeze()crea un oggetto congelato, il che significa che prende un oggetto esistente e lo chiama essenzialmente Object.seal(), ma contrassegna anche tutte le proprietà “accessor dati” come writable:false, in modo che i loro valori non possano essere modificati. - Kyle Simpson, You Know Know JS - Questo e prototipi di oggetti


4

Stavo esaminando le differenze tra Freeze e Seal in ECMAScript 5 e ho creato uno script per chiarire le differenze. Frozen crea un oggetto immutabile che include dati e struttura. Il sigillo impedisce modifiche alle interfacce denominate, senza aggiunte, eliminazioni, ma è possibile mutare l'oggetto e ridefinire il significato della sua interfaccia.

function run()
{
    var myObject = function() 
    { 
        this.test = "testing"; 
    }

    //***************************SETUP****************************

    var frozenObj = new myObject();
    var sealedObj = new myObject();

    var allFrozen = Object.freeze(frozenObj);
    var allSealed = Object.seal(sealedObj);
    alert("frozenObj of myObject type now frozen - Property test= " + frozenObj.test);
    alert("sealedObj of myObject type now frozen - Property test= " + sealedObj.test);

    //***************************FROZEN****************************

    frozenObj.addedProperty = "added Property"; //ignores add
    alert("Frozen addedProperty= " + frozenObj.addedProperty);
    delete frozenObj.test; //ignores delete
    alert("Frozen so deleted property still exists= " + frozenObj.test);
    frozenObj.test = "Howdy"; //ignores update
    alert("Frozen ignores update to value= " + frozenObj.test);
    frozenObj.test = function() { return "function"; } //ignores
    alert("Frozen so ignores redefinition of value= " + frozenObj.test);

    alert("Is frozen " + Object.isFrozen(frozenObj));
    alert("Is sealed " + Object.isSealed(frozenObj));
    alert("Is extensible " + Object.isExtensible(frozenObj));

    alert("Cannot unfreeze");
    alert("result of freeze same as the original object: " + (frozenObj === allFrozen).toString());

    alert("Date.now = " + Date.now());

    //***************************SEALED****************************

    sealedObj.addedProperty = "added Property"; //ignores add
    alert("Sealed addedProperty= " + sealedObj.addedProperty);
    sealedObj.test = "Howdy"; //allows update
    alert("Sealed allows update to value unlike frozen= " + sealedObj.test);
    sealedObj.test = function() { return "function"; } //allows
    alert("Sealed allows redefinition of value unlike frozen= " + sealedObj.test);
    delete sealedObj.test; //ignores delete
    alert("Sealed so deleted property still exists= " + sealedObj.test);
    alert("Is frozen " + Object.isFrozen(sealedObj));
    alert("Is sealed " + Object.isSealed(sealedObj));
    alert("Is extensible " + Object.isExtensible(sealedObj));

    alert("Cannot unseal");
    alert("result of seal same as the original object: " + (sealedObj === allSealed).toString());

    alert("Date.now = " + Date.now());
}

3

So che potrei essere un po 'in ritardo ma

  • Somiglianza: entrambi sono usati per creare oggetti non estensibili .
  • Differenza: in Congela gli attributi configurabili, enumerabili e scrivibili dell'oggetto sono impostati su false. dove come in Sealed l' attributo scrivibile è impostato su truee il resto degli attributi è falso.

6
Questo non è del tutto corretto. Object.getOwnPropertyDescriptor(Object.freeze({ prop: 1 }), 'prop').enumerable=== true.
Leon Adler,

2

Ora puoi forzare il congelamento di una singola proprietà dell'oggetto invece di congelare l'intero oggetto. Puoi farlo con Object.definePropertycon writable: falsecome parametro.

var obj = {
    "first": 1,
    "second": 2,
    "third": 3
};
Object.defineProperty(obj, "first", {
    writable: false,
    value: 99
});

In questo esempio, obj.firstora ha il suo valore bloccato su 99.


0

Ho creato una tabella semplice per confrontare le funzioni seguenti e spiegare la differenza tra queste funzioni.

  • Object.freeze ()
  • Object.seal ()
  • Object.preventExtensions ()

tabella che spiega la differenza tra i tre metodi precedenti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.