I have a global variable in JavaScript (actually a window
property, but I don't think it matters) which was already populated by a previous script, but I don't want another script that will run later to see its value or that it was even defined.
I've put some_var = undefined
and it works for the purpose of testing typeof some_var == "undefined"
but I really do not think it's the right way to go about it.
What do you think?
The delete
operator removes a property from an object. It cannot remove a variable. So the answer to the question depends on how the global variable or property is defined.
(1) If it is created with var
, it cannot be deleted.
For example:
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) If it is created without var
, it can be deleted.
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
Technical Explanation
1. Using var
In this case the reference g_a
is created in what the ECMAScript spec calls "VariableEnvironment" that is attached to the current scope - this may be the a function execution context in the case of using var
inside a function (though it may be get a little more complicated when you consider let
) or in the case of "global" code the VariableEnvironment is attached to the global object (often window
).
References in the VariableEnvironment are not normally deletable - the process detailed in ECMAScript 10.5 explains this in detail, but suffice it to say that unless your code is executed in an eval
context (which most browser-based development consoles use), then variables declared with var
cannot be deleted.
2. Without Using var
When trying to assign a value to a name without using the var
keyword, JavaScript tries to locate the named reference in what the ECMAScript spec calls "LexicalEnvironment", and the main difference is that LexicalEnvironments are nested - that is a LexicalEnvironment has a parent (what the ECMAScript spec calls "outer environment reference") and when JavaScript fails to locate the reference in a LexicalEnvironment, it looks in the parent LexicalEnvironment (as detailed in 10.3.1 and 10.2.2.1). The top level LexicalEnvironment is the "global environment", and that is bound to the global object in that its references are the global object's properties. So if you try to access a name that was not declared using a var
keyword in the current scope or any outer scopes, JavaScript will eventually fetch a property of the window
object to serve as that reference. As we've learned before, properties on objects can be deleted.
Notes
It is important to remember that var declarations are "hoisted" - i.e. they are always considered to have happened in the beginning of the scope that they are in - though not the value initialization that may be done in a var statement - that is left where it is. So in the following code, a is a reference from the VariableEnvironment and not the window property and its value will be 10 at the end of the code: function test() { a = 5; var a = 10; } The above discussion is when "strict mode" is not enabled. Lookup rules are a bit different when using "strict mode" and lexical references that would have resolved to window properties without "strict mode" will raise "undeclared variable" errors under "strict mode". I didn't really understand where this is specified, but its how browsers behave.
scunliffe's answer will work, but technically it ought to be
delete window.some_var;
delete is supposed to be a no-op when the target isn't an object property. e.g.,
(function() {
var foo = 123;
delete foo; // wont do anything, foo is still 123
var bar = { foo: 123 };
delete bar.foo; // foo is gone
}());
But since global variables are actually members of the window object, it works.
When prototype chains are involved, using delete gets more complex because it only removes the property from the target object, and not the prototype. e.g.,
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.
So be careful.
Note: My answer is somewhat inaccurate (see "Misconceptions" at the end). The link explains all the gory details, but the summary is that there can be big differences between browsers and depending on the object you are deleting from. delete object.someProp
should generally be safe as long as object !== window
. I still wouldn't use it to delete variables declared with var
although you can under the right circumstances.
var
is when the variable was declared with eval
.
If you are implicitly declaring the variable without var
, the proper way would be to use delete foo
.
However after you delete it, if you try to use this in an operation such as addition a ReferenceError
will be thrown because you can't add a string to an undeclared, undefined identifier. Example:
x = 5;
delete x
alert('foo' + x )
// ReferenceError: x is not defined
It may be safer in some situations to assign it to false, null, or undefined so it's declared and won't throw this type of error.
foo = false
Note that in ECMAScript null
, false
, undefined
, 0
, NaN
, or ''
would all evaluate to false
. Just make sure you dont use the !==
operator but instead !=
when type checking for booleans and you don't want identity checking (so null
would == false
and false == undefined
).
Also note that delete
doesn't "delete" references but just properties directly on the object, e.g.:
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)
If you have declared a variable with var
you can't delete it:
(function() {
var x = 5;
alert(delete x)
// false
})();
In Rhino:
js> var x
js> delete x
false
Nor can you delete some predefined properties like Math.PI
:
js> delete Math.PI
false
There are some odd exceptions to delete
as with any language, if you care enough you should read:
https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator
http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
See noah's answer for full details
//Option A.) set to null
some_var = null;
//Option B.) set to undefined
some_var = undefined;
//Option C.) remove/delete the variable reference
delete obj.some_var
//if your variable was defined as a global, you'll need to
//qualify the reference with 'window'
delete window.some_var;
References:
MDN delete API
MDN SyntaxError when deleting an unqualified variable name in strict mode
delete
.
delete
only works for a property. Setting it null
the variable still exists.
TLDR: simple defined variables (without var
, let
, const
) could be deleted with delete
. If you use var
, let
, const
- they could not be deleted neither with delete
nor with 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"
Firefox Nightly 53.0a1 shows the same behaviour.
var
case. As for me it was interesting to test and share let
and const
cases as well. However, thanks for note. Will try to be more specific next time.
ECMAScript 2015 offers Reflect API. It is possible to delete an object property with Reflect.deleteProperty():
Reflect.deleteProperty(myObject, 'myProp');
// it is equivalent to:
delete myObject.myProp;
delete myObject['myProp'];
To delete a property of the global window
object:
Reflect.deleteProperty(window, 'some_var');
In some cases properties cannot be deleted (when the property is not configurable) and then this function returns false
(as well as the delete operator). In other cases it returns 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
There is a difference between deleteProperty
function and delete
operator when run in strict mode:
'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
⚠️ The accepted answer (and others) are outdated!
TL;DR
delete does not remove variables. (It's only for removing a property from an object.)
The correct way to "unset" is to simply set the variable to null. (source) (This enables JavaScript's automatic processes to remove the variable from memory.)
Example:
x = null;
😉
More info:
Use of the delete
operator on a variable is deprecated since 2012, when all browsers implemented (automatic) mark-and-sweep garbage-collection. The process works by automatically determining when objects/variables become "unreachable" (deciding whether or not the code still requires them).
With JavaScript, in all modern browsers:
Garbage collection is performed automatically. We cannot force or prevent it. Objects are retained in memory while they are reachable. Being referenced is not the same as being reachable: a pack of interlinked objects can become unreachable as a whole. (source)
The delete
operator is only used to remove a property from an object; it does not remove variables.
Unlike what common belief suggests (perhaps due to other programming languages like delete in C++), the delete operator has nothing to do with directly freeing memory. Memory management is done indirectly via breaking references. (source)
When using strict mode ('use strict';
, as opposed to regular/"sloppy mode") an attempt to delete a variable will throw an error and is not allowed. Normal variables in JavaScript can't be deleted using the delete
operator (source) (or any other way, as of 2021).
...alas, the only solution:
Freeing the contents of a variable
To free the contents of a variable, you can simply set it to null:
var x; // ... x = null; // (x can now be garbage collected)
(source)
Further Reading:
Memory Management (MDN Docs)
Garbage Collection (Örebro University)
The Very Basics of Garbage Collection (javascript.info)
Understanding JavaScript Memory Management using Garbage Collection
Eradicating Memory Leaks In Javascript
null
is a valid value - if setting a variable to null
results in it disappearing (i.e. causing future references to throw ReferenceError: x is not defined
), then a lot of software would break. If you would have said to set it to undefined
, we might have had something to discuss.
null
does not delete it), or it is a property on the global object, in which case delete
will remove it just fine.
Note that delete
returns true
when it was successful.
Update 2021: tested on Chrome 88 and Firefox 84:
implicit_global = 1;
delete implicit_global; // true
window.explicit_global = 1;
delete explicit_global; // true
const _object = {property: 1};
delete _object.property; // true
function_set = function() {};
delete function_set; // true
function function_declaration() {};
delete function_declaration; // false
(function () {
var _var = 1;
console.log(delete _var); // false
console.log(_var); // 1
})()
(function () {
let _let = 1;
console.log(delete _let); // false
console.log(_let); // 1
})()
(function () {
const _const = 1;
console.log(delete _const); // false
console.log(_const); // 1
})()
The previous edit of this answer is no longer relevant due to browser updates.
let
vars and const
vars it is returning true what should means that variable deleted but it is not. You could check it in both in Chrome and FF. FF seems returning correct values while Chrome is not. So don't sure you could really rely on it. Let see: let letVar = "1"; undefined delete letVar; true letVar "1" typeof letVar; "string" const constVar="1"; undefined delete constVar; true constVar; "1" typeof constVar; "string"
delete
operator works. But it is not describing why literally oposite situation with functions. As a pity. However, regarding variables things start appearing to be much more clear.
Variables, in contrast to simple properties, have the attribute [[Configurable]], meaning impossibility to remove a variable via the delete operator.
However, there is one execution context in which this rule does not affect. It is the eval context: there the [[Configurable]] attribute is not set for variables.
The delete operator removes a property from an object.
delete object.property
delete object['property']
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
According to the question you need one of followings
delete some_var;
delete window.some_var;
delete window['some_var'];
delete
actually does is correct but the proposed solution is not the correct method. (See here and also this answer.)
You cannot delete a variable if you declared it (with var x;
) at the time of first use. However, if your variable x
first appeared in the script without a declaration, then you can use the delete
operator (delete x;
) and your variable will be deleted, very similar to deleting an element of an array or deleting a property of an object.
delete
is used to make objects forget about properties being defined, it does not affect variables.
I am bit confused. If all you want is for a variables value to not pass to another script then there isn't any need to delete the variable from the scope.
Simply nullify the variable and then explicit check if it is or is not null. Why go through the trouble of deleting the variable from the scope? What purpose does this serve that nullifying can not?
foo = null;
if(foo === null) or if(foo !== null)
null
value that I don't want to trigger.
<?php if(isset($_POST['somevariable']) unset($_POST['somevariable']); if(isset($_GET['somevariable']) unset($_GET['somevariable']); ?>
Success story sharing
var
outside a function) are properties of the "global object", which in web browsers iswindow
. So -var a = 1; delete window.a; console.log(a);
will successfully delete the variable and cause the last line to issue a reference error.var a = 1; delete window.a; console.log(a);
displays 1.1
correctly in all browsers. Running in real documents, your code examples are correct. I selected your answer as correct, but I'd appreciate it if you can edit it to include explainingwindow.a = 1; delete window.a;
and possibly the mechanism. I can do so as well if you don't mind.