简体   繁体   中英

Can't understand the behavior of deleting vars in JavaScript

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM