Come disinserire una variabile JavaScript?

Ho una variabile globale in JavaScript (in realtà una proprietà della window , ma non penso che sia importante) che era già popolata da uno script precedente ma non voglio che un altro script che verrà eseguito in seguito per vedere il suo valore o che sia stato anche definito.

Ho messo some_var = undefined e funziona allo scopo di testare typeof some_var == "undefined" ma non penso davvero che sia il modo giusto per farlo.

Cosa ne pensi?

So che questo è un thread vecchio, ma la risposta selezionata non è abbastanza chiara per me.

Il punto è che l’operatore delete rimuove una proprietà da un object. Non può rimuovere una variabile. Quindi la risposta alla domanda dipende da come viene definita la variabile globale o la proprietà.

(1) Se è stato creato con var, non può essere cancellato.

Per esempio:

 var g_a = 1; //create with var, g_a is a variable delete g_a; //return false console.log(g_a); //g_a is still 1 

(2) Se è stato creato senza var, può essere cancellato.

 g_b = 1; //create without var, g_b is a property delete g_b; //return true console.log(g_b); //error, g_b is not defined 

Spiegazione tecnica

1. Usando var

In questo caso il riferimento g_a viene creato in quello che la specifica ECMAScript chiama ” VariableEnvironment ” che è collegato all’ambito corrente – questo potrebbe essere il contesto di esecuzione di una funzione nel caso in cui si usi var all’interno di una funzione (anche se potrebbe essere un po ‘ più complicato se si considera let ) o nel caso di codice “globale” il VariableEnvironment è collegato all’object globale (spesso window ).

I riferimenti nel VariableEnvironment non sono normalmente cancellabili – il processo dettagliato in ECMAScript 10.5 lo spiega in dettaglio, ma è sufficiente dire che, a meno che il codice non venga eseguito in un contesto eval (utilizzato dalla maggior parte delle console di sviluppo basate su browser), allora le variabili dichiarate con var non può essere cancellato.

2. Senza l’uso di var

Quando si tenta di assegnare un valore a un nome senza utilizzare la parola chiave var , Javascript cerca di individuare il riferimento denominato in ciò che le specifiche ECMAScript chiama ” LexicalEnvironment ” e la differenza principale è che i nodes di LexicalEvironment sono nidificati, ovvero un ambiente Lexical ha un genitore (ciò che la specifica ECMAScript chiama “riferimento all’ambiente esterno”) e quando Javscript non riesce a localizzare il riferimento in un ambiente Lexical , guarda nel genitore LexicalEnvironment (come descritto in 10.3.1 e 10.2.2.1 ). Il livello più alto LexicalEnvironment è ” l’ambiente globale ” e che è associato all’object globale in quanto i suoi riferimenti sono le proprietà dell’object globale. Quindi, se provate ad accedere ad un nome che non è stato dichiarato usando una parola chiave var nell’attuale scope o in altri ambiti esterni, Javascript recupererà una proprietà dell’object window da servire come riferimento. Come abbiamo imparato prima, le proprietà sugli oggetti possono essere cancellate.

Gli appunti

  1. È importante ricordare che le dichiarazioni var sono “issate” – vale a dire che sono sempre considerate come avvenute all’inizio dell’ambito in cui si trovano – sebbene non l’inizializzazione del valore che può essere eseguita in una dichiarazione var – che è lasciata dove è. Quindi nel codice seguente, a è un riferimento da VariableEnvironment e non dalla proprietà della window e il suo valore sarà 10 alla fine del codice:

    function test() { a = 5; var a = 10; }

  2. La discussione sopra è quando “strict mode” non è abilitata. Le regole di ricerca sono un po ‘diverse quando si utilizza la “modalità rigorosa” ei riferimenti lessicali che avrebbero risolto le proprietà della finestra senza “modalità rigorosa” genererà errori “variabile non dichiarata” in “modalità rigorosa”. Non ho davvero capito dove è specificato, ma come si comportano i browser.

La risposta di @ scunlife funzionerà, ma tecnicamente dovrebbe essere

 delete window.some_var; 

delete dovrebbe essere un no-op quando la destinazione non è una proprietà dell’object. per esempio,

 (function() { var foo = 123; delete foo; // wont do anything, foo is still 123 var bar = { foo: 123 }; delete bar.foo; // foo is gone }()); 

Ma poiché le variabili globali sono in realtà membri dell’object window, funziona.

Quando sono coinvolte catene prototipo, l’uso di delete diventa più complesso perché rimuove solo la proprietà dall’object di destinazione e non dal prototipo. per esempio,

 function Foo() {} Foo.prototype = { bar: 123 }; var foo = new Foo(); // foo.bar is 123 foo.bar = 456; // foo.bar is now 456 delete foo.bar; // foo.bar is 123 again. 

Perciò stai attento.

EDIT: La mia risposta è alquanto imprecisa (vedi “Idee sbagliate” alla fine). Il collegamento spiega tutti i dettagli cruenti, ma il riassunto è che ci possono essere grandi differenze tra i browser e in base all’object da cui si sta eliminando. delete object.someProp dovrebbe generalmente essere sicuro finchè object !== window . Non lo userei ancora per cancellare le variabili dichiarate con var anche se è ansible nelle giuste circostanze.

Se dichiari implicitamente la variabile senza var , il modo corretto sarebbe usare delete foo .

Tuttavia, dopo averlo eliminato, se si tenta di utilizzarlo in un’operazione come aggiunta, verrà generato un ReferenceError perché non è ansible aggiungere una stringa a un identificatore non dichiarato non definito. Esempio:

 x = 5; delete x alert('foo' + x ) // ReferenceError: x is not defined 

In alcune situazioni potrebbe essere più sicuro assegnarlo a false, null o undefined, quindi è dichiarato e non genererà questo tipo di errore.

 foo = false 

Notare che in ECMAScript null , false , undefined , 0 , NaN o '' valuteranno tutti su false . Assicurati solo di non usare l’operatore !== , ma invece != Quando esegui il controllo dei booleani e non vuoi il controllo dell’identity framework (quindi null == false e false == undefined ).

Si noti inoltre che delete non “elimina” i riferimenti ma solo le proprietà direttamente sull’object, ad esempio:

 bah = {}, foo = {}; bah.ref = foo; delete bah.ref; alert( [bah.ref, foo ] ) // ,[object Object] (it deleted the property but not the reference to the other object) 

Se hai dichiarato una variabile con var non puoi cancellarla:

 (function() { var x = 5; alert(delete x) // false })(); 

In Rhino:

 js> var x js> delete x false 

Né puoi cancellare alcune proprietà predefinite come Math.PI :

 js> delete Math.PI false 

Ci sono alcune strane eccezioni da delete come con qualsiasi lingua, se tieni abbastanza a sufficienza dovresti leggere:

 some_var = null; //or remove it.. delete some_var; 

TLDR: semplici variabili definite (senza var , let , const ) potrebbero essere cancellate con delete . Se usi var , let , const – non possono essere cancellati né con delete né con Reflect.deleteProperty .

Chrome 55:

 simpleVar = "1"; "1" delete simpleVar; true simpleVar; VM439:1 Uncaught ReferenceError: simpleVar is not defined at :1:1 (anonymous) @ VM439:1 var varVar = "1"; undefined delete varVar; false varVar; "1" let letVar = "1"; undefined delete letVar; true letVar; "1" const constVar="1"; undefined delete constVar; true constVar; "1" Reflect.deleteProperty (window, "constVar"); true constVar; "1" Reflect.deleteProperty (window, "varVar"); false varVar; "1" Reflect.deleteProperty (window, "letVar"); true letVar; "1" 

FF Nightly 53.0a1 mostra lo stesso comportamento.

ECMAScript 2015 offre l’API Reflect. È ansible eliminare la proprietà dell’object con Reflect.deleteProperty () :

 Reflect.deleteProperty(myObject, 'myProp'); // it is equivalent to: delete myObject.myProp; delete myObject['myProp']; 

Per cancellare la proprietà dell’object globale della window :

 Reflect.deleteProperty(window, 'some_var'); 

In alcuni casi le proprietà non possono essere cancellate (quando la proprietà non è configurabile) e quindi questa funzione restituisce false (così come cancella operatore ). In altri casi restituisce true :

 Object.defineProperty(window, 'some_var', { configurable: false, writable: true, enumerable: true, value: 'some_val' }); var frozen = Object.freeze({ myProperty: 'myValue' }); var regular = { myProperty: 'myValue' }; var blank = {}; console.log(Reflect.deleteProperty(window, 'some_var')); // false console.log(window.some_var); // some_var console.log(Reflect.deleteProperty(frozen, 'myProperty')); // false console.log(frozen.myProperty); // myValue console.log(Reflect.deleteProperty(regular, 'myProperty')); // true console.log(regular.myProperty); // undefined console.log(Reflect.deleteProperty(blank, 'notExistingProperty')); // true console.log(blank.notExistingProperty); // undefined 

Esiste una differenza tra la funzione deleteProperty e l’operatore delete quando viene eseguita in modalità strict:

 'use strict' var frozen = Object.freeze({ myProperty: 'myValue' }); Reflect.deleteProperty(frozen, 'myProperty'); // false delete frozen.myProperty; // TypeError: property "myProperty" is non-configurable and can't be deleted 

L’operatore delete rimuove una proprietà da un object.

 delete object.property delete object['property'] 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete

Secondo la domanda hai bisogno di uno dei seguenti

 delete some_var; delete window.some_var; delete window['some_var']; 

Oltre a ciò che tutti avevano scritto, nota anche che delete restituisce booleano. Può dirti se l’eliminazione ha avuto successo o meno.

AGGIORNARE:

Test sull’ultimo Chrome, tutto è stato delelettato. delete funzione di delete restituito true per tutti i seguenti metodi e li ha effettivamente rimossi:

 implicit_global = 1; window.explicit_global = 1; function_set = function() {}; function function_dec() { }; var declared_variable = 1; delete delete implicit_global; // true, tested on Chrome 52 delete window.explicit_global; // true, tested on Chrome 52 delete function_set; // true, tested on Chrome 52 delete function_dec; // true, tested on Chrome 52 delete declared_variable; // true, tested on Chrome 52 

Le variabili, in contrasto con le proprietà semplici, hanno attributo [[Configurable]] , che significa impossibilità di rimuovere una variabile tramite l’operatore delete . Tuttavia, esiste un contesto di esecuzione in cui questa regola non influisce. È il contesto di valutazione : l’attributo [[Configurable]] non è impostato per le variabili.

Non è ansible eliminare una variabile se l’hai dichiarata (con var x;) al momento del primo utilizzo. Tuttavia, se la variabile x prima appariva nello script senza una dichiarazione, allora puoi usare l’operatore delete (cancella x;) e la tua variabile sarà cancellata, molto simile all’eliminazione di un elemento di una matrice o all’eliminazione di una proprietà di un object .