Please consider the following snippet (fiddle here):
var a;
a = 1;
console.log(delete a); // prints 'false'
b = 1;
console.log(delete b); // prints 'true'
Why does the delete keywords behave differently on the global variables a and b?
From the MDN docs:
The delete operator removes a property from an object.
A global variable (without var) is a property on the global object (typically window), so can be deleted.
A var is not a global variable, but a local variable in the outer scope - not a property of the global object - so delete does not delete it. From those docs:
x = 42; // creates the property x on the global object
var y = 43; // declares a new variable, y
delete x; // returns true (x is a property of the global object and can be deleted)
delete y; // returns false (delete doesn't affect variable names)
MDN says delete returns false only if the property exists and cannot be deleted. It returns true in all other cases. After deleting, try testing the actual values. You'll see that a was not deleted. This is because, as the MDN page says, delete will not affect variable names.
It has no effect on variable or function names.
(i.e., defined with var and not off the global object)
Take a look at the examples on the following page.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/delete
From mozilla docs about var :
The difference is that a declared variable is a non-configurable property of the global object while an undeclared is configurable.
var a; --> This is a declared variable, because you are using var, so it's not configurable.
a = 6; --> This is an undeclared variable, because you are not using var, so it's configurable.
both syntaxes above will end up with a var named a attached as a property of the global object (window typically) and properties has these attributes:
Writable. If false, the value of the property can not be changed.
Configurable. If false, any attempts to delete the property or change its attributes (Writable, Configurable, or Enumerable) will fail.
Enumerable. If true, the property will be iterated over when a user does for (var prop in obj){} (or similar).
that is extracted from ecmascript5 objects and properties , and as you can read, the configurable attribute of the variable in question affects whether the variable can or cannot be deleted.
"var a" means it cannot be accessed from anywhere outside of the current block, thus deleting it WOULD mean UNDECLARE (not same as undefined), thus allowing to write "var a" again in the same block (error).
Allowed usages (MDN):
delete object.property
delete object['property']
delete object[index]
delete property
It's like GOTO and unstructured programming, where you might need to manually clean up resources, it's kind of ~Destructor in C (though not the same). You can delete an object like ~a(); but you cannot "'UNDECLARE' a variable" like "int i".
Related
var sum = function(a, b) {return a + b;};
var add = sum;
delete sum;
After Executing Delete it return False in console. Ideally it should return True.
Why sum function is not deleted?
Note above code is executed in google chrome browser console.
From MDN:
The delete operator removes a given property from an object.
If the property which you are trying to delete does not exist, delete will not have any effect and will return true.
If a property with the same name exists on the object's prototype chain, then, after deletion, the object will use the property from the prototype chain (in other words, delete only has an effect on own properties).
Any property declared with var cannot be deleted from the global scope or from a function's scope.
As such, delete cannot delete any functions in the global scope (whether this is part from a function definition or a function expression).
Functions which are part of an object (apart from the global scope) can be deleted with delete.
Hence sum which is a function attached to the global scope, cannot be deleted with delete.
delete cannot delete with direct member .
The delete operator removes a property from an object.
Since you giving sum and not telling from which object you want to remove it.
What you looking for is
delete window.sum
Now it removes the sum from window object :)
demo
Refer MDN
The delete operator removes a property from an object.
Any property declared with var cannot be deleted from the global scope or from a function's scope.
As such, delete cannot delete any functions in the global scope (whether this is part from a function definition or a function expression).
Functions which are part of an object (apart from the global scope) can be deleted with delete.
Here I found information hot to works scope chain:
...before we go to the parent link, first proto chain is
considered.
Notice, that not in all implementations the global object inherits
from the Object.prototype. The behavior described on the figure (with
referencing “non-defined” variable x from the global context) may be
tested e.g. in SpiderMonkey.
I use Firefox browser for testing, but, when I set global variable x, and set to Object.prototype property x and do a() I've got 4. Why, if first we go to proto?
var x = 1;
Object.prototype.x = 2;
var a = function () {
y = 3;
return this.y + this.x;
};
a.x; // 2
a(); // 4
You should've cited the beginning of that paragraph, not the end:
At code execution, a scope chain may be augmented using with statement and catch clause objects.
So what your sentence refers to are only object environment records - scope objects in which variables live. Those are typically imaginary, described for specification purposes only (and can only be observed in Rhino), but the with statement makes an exception and prepends an actual JS object to the scope chain.
If you check out the example, you will find the with statement right there. The gist:
Object.prototype.x = "inherited object property";
var x = "parent scope variable";
with ({}) {
alert(x); // you bet what it yields
}
When I set global variable x, and set Object.prototype.x property, why doesn't it get the prototype value?
By using this in a function that is called plainly (a()), you are referring to the global object. It is indeed the object for the object environment record of the global scope, which means that all global variables live there as properties.
Now why does accessing x on that object (regardless whether by variable x or property this.x) bring up 1 not 2? Because the global variable with the value 1 is an own property of the object. The prototype chain will only be traversed if the property is not already found!
What is the difference between the JavaScript Global object and Window object. I know in both, you don't have to declare the object to use the methods.
The window object encapsulates the global scope. Omitting var (or let) when declaring a variable will implicitly add that as a property to the global scope. It's unique in that sense since there is no equivalent to window when inside a different scope.
I'm going to quote myself on this one:
MDN's description of var states that the global scope is bound to the global object. This would suggest that declaring a variable (either with var at the top level, or without var inside a function) simply adds a new property to window (or an equivalent outside of the browser).
Try it out. Create a variable without using var, then look at the window object in your console. You'll see it in there. It's the equivalent of doing this:
Object.defineProperty(window, 'foo', {
value: "bar",
enumerable: true // see #dandavis' comment on iterating over implicit global vars
)}
This doesn't explain why that's the case. Just that window is unique in that everything is defined within it.
I could be wrong, but it seems to me that the so-called globals are defined under the window object.
In JavaScript that is running in a browser, window is at the top of the scope chain. If you define a "global" variable, it is implied that it is under the window object.
For example:
// Global variable
var g = 0;
function foo(){
window.g = 1
// This will output '1'
alert(g);
}
Here is the issue:
var x = 5;
window.x === x // true. x, as it seems, is a property of window
delete x; // false
delete window.x; // false;
BUT
window.x = 5;
delete window.x; // true
AND
window.x = 5;
delete x; // true
What is the explanation for such behavior?
Essentially the reason is that declared variables are created with an internal DontDelete attribute, while properties created via assignment are not.
Here is great article explaining the inner details of delete: Understanding delete
When declared variables and functions become properties of a Variable
object — either Activation object (for Function code), or Global
object (for Global code), these properties are created with DontDelete
attribute. However, any explicit (or implicit) property assignment
creates property without DontDelete attribute. And this is essentialy
why we can delete some properties, but not others:
You can use delete only for deleting objects, object properties or array element.
delete expression
delete will be not working if expression can't be represented
as property. So delete can remove global variable, but not variables inited by var.
So, let me explain:
var x = 5;
You create variable in global scope by var, not property of window object. This var is just linked to window.x. And then you compare window.x === x it will return true. But:
delete x; // deleting variable, not property, return false
delete window.x; // resolve link to x and also deleting variable, not property, return false
BUT
window.x = 5;//add property
delete window.x; // can delete property, return true
AND
window.x = 5;//add property
delete x; //resolve x. it's a propery of window, return true
and older
In ECMAScript 262/3 as #Peter explain is available DontDelete flag. But in ECMAScript 262/5.1 in strict mode deleting is regulated by Configurable flag:
When a delete operator occurs within strict mode code, a SyntaxError
exception is thrown if its UnaryExpression is a direct reference to a
variable, function argument, or function name. In addition, if a
delete operator occurs within strict mode code and the property to be
deleted has the attribute { [[Configurable]]: false }, a TypeError
exception is thrown.
This is how I understand that:
var x = 5; declared in the global scope creates the new window property x.
window.x = 5; declared (whereever) creates the new window property x as well. That's why window.x === x gives you true.
The difference is that javascript by default sets different descriptors for x property according to the way (one of two above) it is declared.
var x = 5 is equal to:
Object.defineProperty(window,'x',{
value: 5,
writable: true,
enumerable: true,
configurable: false
});
while window.x = 5 is equal to:
Object.defineProperty(window,'x',{
value: 5,
writable: true,
enumerable: true,
configurable: true
});
The configurable descriptor, if false, forbides to delete the property.
We can assume, that javascript use Object.defineProperty with different descriptor settings under the hood when we declare variables in a simple way with var keyword or without it (automatically assigned to window).
You can simply check that:
var x = 5;
window.y = 5;
console.log(Object.getOwnPropertyDescriptor(window,'x')); //configurable:false
console.log(Object.getOwnPropertyDescriptor(window,'y')); //configurable:true
I was reading this article on the Javascript delete method, and tried this code:
function f(){
var x = "abcd";
console.log(delete x); //returns false, because x has DontDelete attribute
y = "abcd";
console.log(delete y); //returns true, but I didn't explicitly assign y as a property
}
This is strange, because I am not using property assignment for y (as in: window.y="abcd";), which the article claims is how you make properties deleteable.
Why does y not have the DontDelete attribute?
UPDATE:
In the answers below, it is claimed that y is deleteable merely because it is a property of the window object. That is not true. Consider the following snippet:
function f() {
var functionx = "abcd";
console.log(delete functionx); //returns false, because x has DontDelete attribute
functiony = "abcd";
console.log(delete functiony); //returns true, but I didn't explicitly assign functiony as a property to the window
}
//take 1
var globalx = "abcd";
console.log(this.globalx);//to prove x is a property of the global
console.log(delete globalx);//fails, even though x is a property of the window
//take 2
this.globaly = "abcd";
console.log(this.globaly);//to prove y is a property of the global
console.log(delete globaly);//succeeds, because I used property assignment
f();
In take 1, globalx is a property of the window, but it is still undeleteable. The criteria for whether delete will succeed is not whether the variable is a property of something (which is always true), but whether that property has a DontDelete attribute set.
delete x is invalid because it does not resolve to any object property.
y resolves to a property of the window object.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/delete:
delete expression
where expression should evaluate to a property reference
Here is the expanded version of the second example:
window.y = "abcd";
console.log(delete window.y);
It's pretty obvious now what's happening.
If you don't use the var keyword, the interpreter assumes the variable is a property of the global object, (which is usually window), as shown in this JSFiddle. Note that in the global scope, this is the same as the window object.
Re: Update:
Outside a function, a variable declared with var is defined as a non-configurable property of the global object. This is detailed in https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/var, where it says:
Using var outside a function is optional; assigning a value to an undeclared variable implicitly declares it as a global variable (also a property of the global object). The difference is that a declared variable is a non-configurable property of the global object while an undeclared is configurable.
Declaring a variable inside a function does not assign it to a global property, but rather a local variable.
That explains the behaviour you're seeing when defining a variable in the global scope.
Variables in JavaScript are declared using var keyword. When you omit var, the interpreter starts looking for the closest scope in which the given variable is defined. If the given variable is not found, it will be created as a new property on a global object.
This is exactly what happens here:
Variable y is referenced and assigned a new value (abcd)
Var y is not defined anywhere → new global property y is created and assigned the value (effectively window.y = "abcd").
As a result, y becomes property of the global object, which can be deleted.