1. Raising the question Let’s first take a look at the following pieces of code. It should be noted that the following code should not be used in the browser’s developer tools (such as FireBug, Chrome Developer tool) Run in, the reason will be explained later:
Why we can delete the attributes of the object:
var o = { x: 1 };
delete o.x; // true
o.x; // undefined
But not delete like Variables declared like this:
var x = 1;
delete x; // false
x; // 1
You cannot also delete functions defined like this:
function x(){}
delete x; // false
typeof x; // "function"
Note: When the delete operator returns true, it means it can be deleted, and when it returns false, it means it cannot be deleted
To understand this, we first need to master concepts like variable instantiation and attribute characteristics - -Unfortunately, these contents are rarely mentioned in some JavaScript books. It's not difficult to understand them, and you can feel free to skip this part if you don't care why they work the way they do.
2. Code types There are three types of executable code in ECMAScript: Global code (global code), Function code (function code) and Eval code ( code executed in Eval).
var x=1;//Global code
function test(){
var y=2;//Function Code
eval("var z=3");//Eval Code in Function
}
eval("function evalTest() {}");//Eval Code in Global
3. Execution context When the ECMAScript code is executed, it is always in a certain Execution context is a somewhat abstract entity that helps us understand how scope and variable instantiation work. For each of the three types of executable code, there is an execution context. When a function executes, control can be said to enter the execution context of the function code. When global code is executed, it enters the execution context of global code (Global code).
As you can see, the execution context logically comes from a stack. First, it may be global code with its own scope. The code may call a function, which has its own scope. The function can call another function, and so on. Even if the function calls itself recursively, each call enters a new execution context.
4. Activation object/Variable object
Each execution context has a Variable Object inside it. Similar to execution context, a Variable object is an abstract entity used to describe the mechanism of variable instantiation. What's interesting is that the variables and functions declared in the code are actually added as properties of this variable object.
When entering the execution context of global code, a global object is used as a variable object. This is why variables or functions declared in the global scope become properties of the global object.
/* remember that `this` refers to global object when in global scope */
var GLOBAL_OBJECT = this;
var foo = 1;
GLOBAL_OBJECT.foo; // 1
foo === GLOBAL_OBJECT.foo; // true
function bar(){}
typeof GLOBAL_OBJECT.bar; // "function"
GLOBAL_OBJECT.bar === bar; // true
Global variables become properties of the global object, but what about local variables defined in function code? The behavior is actually very similar: it becomes a property of the variable object. The only difference is that in Function code, the variable object is not a global object, but a so-called Activation object. Every time function code enters the execution scope, an activation object is created.
Not only the variables and functions in the function code become properties of the activation object, but also each parameter of the function (the name corresponding to the formal parameter) and a specific Arguments object. Note that the activation object is an internal mechanism and is not actually accessed by program code.
(function(foo){
var bar = 2;
function baz(){}
/*
In abstract terms,
Special `arguments` object becomes a property of containing function's Activation object:
ACTIVATION_OBJECT.arguments; // Arguments object
...as well as argument `foo`:
ACTIVATION_OBJECT.foo; // 1
...as well as variable `bar`:
ACTIVATION_OBJECT.bar; // 2
...as well as function declared locally:
typeof ACTIVATION_OBJECT.baz; // "function"
*/
})(1);
Finally, variables declared in the Eval code are created as properties of the variable object of the calling context. Eval code only uses the variable object of the execution context in which it is being called.
var GLOBAL_OBJECT = this;
/ * `foo` is created as a property of calling context Variable object,
which in this case is a Global object */
eval('var foo = 1;');
GLOBAL_OBJECT. foo; // 1
(function(){
/* `bar` is created as a property of calling context Variable object,
which in this case is an Activation object of containing function */
eval('var bar = 1;');
/*
In abstract terms,
ACTIVATION_OBJECT.bar; // 1
* /
})();
5. Attribute Characteristics
Now it is clear what will happen to the variables (they become attributes), and the only thing left is The concept that needs to be understood is attributes. Each attribute has zero or more attributes from the following set of attributes - ReadOnly, DontEnum, DontDelete and Internal. You can think of them as a tag, an attribute that is optional. For the purposes of today's discussion, we are only interested in the DontDelete attribute.
When declared variables and functions become properties of a variable object - either the activation object (Function code) or the global object (Global code), these created properties have the DontDelete attribute. However, any explicitly (or implicitly) created properties do not have the DontDelete attribute. This is why some properties can be deleted and some cannot.
var GLOBAL_OBJECT = this;
/ * `foo` is a property of a Global object.
It is created via variable declaration and so has DontDelete attribute.
This is why it can not be deleted. */
var foo = 1;
delete foo; // false
typeof foo; // "number"
/* `bar` is a property of a Global object.
It is created via function declaration and so has DontDelete attribute.
This is why it can not be deleted either. */
function bar(){}
delete bar; // false
typeof bar; // "function"
/* `baz` is also a property of a Global object.
However, it is created via property assignment and so has no DontDelete attribute.
This is why it can be deleted. */
GLOBAL_OBJECT.baz = 'blah';
delete GLOBAL_OBJECT.baz; // true
typeof GLOBAL_OBJECT.baz; // "undefined"
6. Built-in attributes and DontDelete
In a word: A unique characteristic (DontDelete) in the attribute controls whether this attribute can be deleted. Note that the object's built-in properties (that is, the object's predefined properties) have the DontDelete attribute and therefore cannot be deleted. Specifically the Arguments variable (or, as we now know, the activation object's properties), the length property of any function instance also has the DontDelete attribute.
(function(){
/* can't delete `arguments`, since it has DontDelete */
delete arguments; // false
typeof arguments ; // "object"
/* can't delete function's `length`; it also has DontDelete */
function f(){}
delete f.length; / / false
typeof f.length; // "number"
})();
The properties created corresponding to the function parameters also have the DontDelete attribute, so they also cannot be deleted.
(function(foo, bar){
delete foo; // false
foo; // 1
delete bar; // false
bar; // 'blah'
})(1, ' blah');
7. Undeclared assignment Simply undeclared assignment creates a deletable object on a global object properties.
var GLOBAL_OBJECT = this;
/ * create global property via variable declaration; property has DontDelete */
var foo = 1;
/* create global property via undeclared assignment; property has no DontDelete */
bar = 2;/ /Can be understood as window.bar=2; According to the fifth point above, it can be deleted
delete foo; // false
typeof foo; // "number"
delete bar; // true
typeof bar; // "undefined"
Please note that the DontDelete attribute is determined during the property creation process, and subsequent assignments will not modify existing properties. It is important to understand the nature of existence.
/* `foo` is created as a property with DontDelete */
function foo(){}
/* Later assignments do not modify attributes. DontDelete is still there! */
foo = 1;
delete foo; // false
typeof foo; // "number"
/* But assigning to a property that doesn't exist,
creates that property with empty attributes (and so without DontDelete) */
this.bar = 1;
delete bar; // true
typeof bar; // "undefined"
8. Eval code
Variables or methods created in Eval are special and do not have the DontDelete attribute, which means they can be deleted.
eval("var x = 1;" );
console.log(x); // 1
delete x;
console.log(typeof x); // undefined
eval("function test(){ var x=1; console.log(delete x);/* false */;return 1;}");
console.log(test()); // 1
delete test;
console .log(typeof test); // undefined
Note that the variables or methods created in Eval here do not include variables or methods inside the method, such as the red part in the above code, still Same as what I said before: it cannot be deleted.
9. Confusion about FireBug
Let’s look at the result of a piece of code executed in FireBug:
var x=1;
delete x;
console.log(typeof x);//undefined
function y(){
var z=1;
console.log(delete z);//false
}
y();
delete y;
console.log(typeof y);//undefined
This is obviously against the above rules, but after comparing with the eighth point above, it is found that this is the effect of the code being executed in eval. Although not confirmed, I guess the console code in FireBug (Chrome Developer tool) is executed using eval.
So, when you are testing JS code, you should pay special attention if it involves the current context.
10. Objects deleted by delete operator There is also delete operator in C, which deletes the object pointed to by the pointer. For example:
class Object {
public :
Object *x;
}
Object o;
o.x = new Object();
delete o.x; // The new Object object in the previous line will be released
But Javascript's delete is different from C. It does not delete the object pointed to by o.x, but deletes the o.x attribute itself.
var o = {};
o.x = new Object();
delete o.x; // The new Object object in the previous line still exists
o.x; // undefined, the attribute named x of o is deleted
In actual In Javascript, after deleting o.x, the Object object will be garbage collected because it has lost its reference, so deleting o.x is "equivalent to" deleting the object pointed to by o.x, but this action is not an ECMAScript standard. In other words, even if If an implementation does not delete the Object object at all, it does not violate the ECMAScript standard.
"Deleting attributes instead of deleting objects" can be confirmed by the following code.
var o = {};
var a = { x: 10 };
o.a = a;
delete o.a; // The o.a attribute is deleted
o.a; // undefined
a.x; // 10, because the { x: 10 } object remains It is referenced by a, so it will not be recycled
In addition, delete o.x can also be written as delete o["x"], both of which have the same effect.
11. Other attributes that cannot be deleted
In addition to the built-in attributes (i.e. predefined attributes) mentioned above that cannot be deleted, the attributes declared in the prototype It cannot be deleted:
function C() { this.x = 42; }
C.prototype.x = 12;
C.prototype.y = 13;
var o = new C();
o.x; // 42, construction o.x defined in the function
delete o.x; //true deletes the x defined by itself
o.x; // 12, o.x defined in the prototype will not be deleted even if delete o.x is executed again
delete o.y; //true, because o itself does not have the o.y attribute, and y exists in the prototype chain, which means that the object's own attributes and the prototype attributes are different
o.y; //13
Summary
I have said so much, I hope it will be helpful for everyone to understand Delete in JavaScript. Due to the limited level, there is no guarantee that it is completely correct. If you find any errors, please correct them.
The original text is:
1.
http://perfectionkills.com/understanding-delete/(English)
2.
http://nanto.asablo .jp/blog/2008/01/09/2552470(Japanese)
This article was first published at http://jscode.cnblogs.com