web-dev-qa-db-fra.com

Comment désactiver une variable JavaScript?

J'ai une variable globale en JavaScript (en fait une propriété window, mais je ne pense pas que cela compte) qui était déjà renseignée par un script précédent, mais je ne souhaite pas qu'un autre script s'exécute plus tard pour afficher sa valeur. ou qu'il était même défini.

J'ai mis some_var = undefined et cela fonctionne dans le but de tester typeof some_var == "undefined" mais je ne pense vraiment pas que ce soit la bonne façon de s'y prendre.

Qu'est-ce que tu penses?

561
Guss

L'opérateur delete supprime une propriété d'un objet. Il ne peut pas supprimer une variable. La réponse à la question dépend donc de la définition de la variable globale ou de la propriété.

(1) S'il est créé avec var, il ne peut pas être supprimé.

Par exemple:

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) S'il est créé sans var, il peut être supprimé.

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

Explication technique

1. Utiliser var

Dans ce cas, la référence g_a est créée dans ce que la spécification ECMAScript appelle " VariableEnvironment " est attaché à la portée actuelle - cela peut être le contexte d'exécution d'une fonction dans le cas d'utilisation de var dans une fonction (bien que cela puisse être un peu plus compliqué lorsque vous considérez let) ou dans le cas de code "global" le VariableEnvironment est attaché à l'objet global (souvent window).

Les références dans VariableEnvironment ne sont pas normalement supprimables - le processus détaillé dans ECMAScript 10.5 explique cela en détail, mais cela suffit Cela signifie que si les codes ne sont pas exécutés dans un contexte eval (utilisé par la plupart des consoles de développement basées sur un navigateur), les variables déclarées avec var ne peuvent pas être supprimées.

2. Sans utiliser var

Lorsque vous essayez d'attribuer une valeur à un nom sans utiliser le mot clé var, Javascript essaie de localiser la référence nommée dans ce que la spécification ECMAScript appelle " LexicalEnvironment ", et la principale différence est que LexicalEvironment s sont imbriqués - c’est un LexicalEnvironment a un parent (ce que la spécification ECMAScript appelle "référence d'environnement externe") et lorsque Javscript ne parvient pas à localiser la référence dans un LexicalEenvironment , il recherche dans le parent LexicalEnvironment (comme indiqué dans 10.3.1 et 10.2.2.1 ). Le niveau supérieur LexicalEnvironment est le " environnement global ", et qui est lié à l'objet global en ce sens que ses références sont les propriétés de l'objet global. Donc, si vous essayez d'accéder à un nom qui n'a pas été déclaré à l'aide d'un mot clé var dans la portée actuelle ou dans les portées externes, Javascript récupérera éventuellement une propriété de l'objet window pour servir de référence. Comme nous l'avons appris précédemment, les propriétés des objets peuvent être supprimées.

Remarques

  1. Il est important de se rappeler que les déclarations var sont "levées" - c’est-à-dire qu’elles sont toujours considérées comme ayant eu lieu au début de la portée, bien qu’il ne s’agisse pas de l’initialisation de la valeur pouvant être effectuée dans un var déclaration - qui est laissé où il est. Donc, dans le code suivant, a est une référence de la propriété VariableEnvironment et non de la propriété window et sa valeur sera 10 à la fin du code:

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

  2. La discussion ci-dessus a lieu lorsque le "mode strict" n'est pas activé. Les règles de consultation sont un peu différentes lorsque vous utilisez le "mode strict" et les références lexicales résolues en propriétés de fenêtre sans "mode strict" généreront des erreurs "variable non déclarée" sous le "mode strict". Je n'ai pas vraiment compris où cela est spécifié, mais c'est la façon dont les navigateurs se comportent.

404
Dayong

La réponse de @ scunlife fonctionnera, mais techniquement elle devrait l'être

delete window.some_var; 

delete est supposé être un no-op lorsque la cible n'est pas une propriété d'objet. par exemple.,

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

Mais comme les variables globales sont en réalité des membres de l'objet window, cela fonctionne.

Lorsque des chaînes de prototypes sont impliquées, l'utilisation de la suppression devient plus complexe car elle supprime uniquement la propriété de l'objet cible, et non du prototype. par exemple.,

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.

Donc sois prudent.

EDIT: Ma réponse est quelque peu inexacte (voir "idées fausses" à la fin). Le lien explique tous les détails sanglants, mais le résumé est qu'il peut y avoir de grandes différences entre les navigateurs et selon l'objet que vous supprimez. delete object.someProp devrait généralement être sûr tant que object !== window. Je ne l'utiliserais toujours pas pour supprimer les variables déclarées avec var bien que vous puissiez le faire dans les bonnes circonstances.

274
noah

Si vous déclarez implicitement la variable sans var, la méthode appropriée consiste à utiliser delete foo.

Cependant, après l'avoir supprimé, si vous essayez de l'utiliser dans une opération telle que l'ajout d'un ReferenceError sera levé car vous ne pouvez pas ajouter de chaîne à un identificateur non déclaré, non défini. Exemple:

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

Dans certaines situations, il peut être plus sûr de l'attribuer à false, null ou indéfini afin qu'il soit déclaré et ne génère pas ce type d'erreur.

foo = false

Notez que dans ECMAScript null, false, undefined, 0, NaN ou '' serait évalué à false. Assurez-vous simplement que vous n'utilisez pas l'opérateur !==, mais plutôt != lors de la vérification de types booléens et que vous ne voulez pas de vérification d'identité (donc null voudrait que == false et false == undefined).

Notez également que delete ne "supprime" pas les références, mais uniquement les propriétés directement sur l'objet, par exemple:

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)

Si vous avez déclaré une variable avec var, vous ne pouvez pas la supprimer:

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

Dans Rhino:

js> var x
js> delete x
false

Vous ne pouvez pas non plus supprimer certaines propriétés prédéfinies telles que Math.PI:

js> delete Math.PI
false

Il existe quelques exceptions étranges à delete comme dans n'importe quelle langue, si vous vous en souciez suffisamment, vous devriez lire:

34
meder omuraliev
some_var = null;

//or remove it..
delete some_var;
29
scunliffe

TLDR: les variables définies simples (sans var, let, const) pourraient être supprimées avec delete. Si vous utilisez var, let, const, ils ne pourront être supprimés ni avec delete ni avec Reflect.deleteProperty.

Chrome 55:

simpleVar = "1";
"1"
delete simpleVar;
true
simpleVar;
VM439:1 Uncaught ReferenceError: simpleVar is not defined
    at <anonymous>: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 montre le même comportement.

14
Serj.by

ECMAScript 2015 propose l'API Reflect. Il est possible de supprimer une propriété d'objet avec Reflect.deleteProperty () :

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

Pour supprimer la propriété de l'objet global window:

Reflect.deleteProperty(window, 'some_var');

Dans certains cas, les propriétés ne peuvent pas être supprimées (lorsque la propriété n'est pas configurable), puis cette fonction renvoie false (ainsi que opérateur de suppression ). Dans les autres cas, retourne 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

Il existe une différence entre la fonction deleteProperty et l'opérateur delete lorsqu'il est exécuté en mode 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
3
madox2

L'opérateur delete supprime une propriété d'un objet.

delete object.property
delete object['property']

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

Selon la question, vous avez besoin de l'un des suivants

delete some_var;
delete window.some_var;
delete window['some_var'];
2
Swarnendu Paul

Les variables, contrairement aux propriétés simples, ont l'attribut [[Configurable]], ce qui signifie qu'il est impossible de supprimer une variable via la commande delete opérateur. Cependant, il existe un contexte d'exécution sur lequel cette règle n'a pas d'incidence. C'est le contexte eval: l'attribut [[Configurable]] n'est pas défini pour les variables.

2
Eldiyar Talantbek

En plus de ce que tout le monde a écrit, notez également que delete renvoie un booléen. Il peut vous dire si la suppression a réussi ou non.

PDATE:

Test sur la dernière version de Chrome, tout était parfait. La fonction delete a renvoyé true pour toutes les méthodes suivantes et les a réellement supprimées:

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
2
oriadam

Vous ne pouvez pas supprimer une variable si vous l'avez déclarée (avec var x;) lors de la première utilisation. Cependant, si votre variable x est apparue pour la première fois dans le script sans déclaration, vous pouvez utiliser l'opérateur delete (delete x;) et votre variable sera supprimée, ce qui est très similaire à la suppression d'un élément d'un tableau ou à la suppression d'une propriété d'un objet. .

1
Satyapriya Mishra

Je suis un peu confus. Si tout ce que vous voulez, c'est qu'une valeur de variable ne soit pas transmise à un autre script, il n'est pas nécessaire de supprimer la variable de la portée. Annulez simplement la variable, puis vérifiez de manière explicite si elle est ou non nulle. Pourquoi avoir la peine de supprimer la variable de la portée? Quel est le but de ce serveur que l'annulation ne peut pas?

foo = null;
if(foo === null) or if(foo !== null)
0
designdrumm