[Go] deep into the JavaScript delete operator

Source: Internet
Author: User
Tags getbase

Recently re-review JS, the delete operator has been in the state of smattering, accidentally found an article, this made a very detailed explanation, read the feeling of enlightened, dare not exclusive, roughly translated as follows.

Original address: http://perfectionkills.com/understanding-delete/

P.s. Author is a member of Prototypejs's development team

======== Split Line ========

Before we get started, let's look at a piece of code

JS Code
    1. >>> var sum = function (A, b) {return a + B;}
    2. >>> var add = sum;
    3. >>> Delete sum
    4. True
    5. >>> typeof sum;
    6. "Undefined"

This code is the actual result in the Firebug console, and at the beginning of this code, what do you think is the problem? But what I'm saying is that deleting sum should be a failure, and the result of typeof sum should not be undefined, because variables declared in JavaScript in this way cannot be deleted.

So where's the problem? To answer this question, we need to understand the implementation details of the delete operator in various situations, and then look back at the seemingly "bizarre" output of Firebug.

P.S there is no special declaration, the JavaScript mentioned below refers to the ECMAScript specification.

1. Theory

The delete operator is typically used to delete an object's properties:

JS Code
    1. var o = {x:1};
    2. Delete o.x; True
    3. o.x; Undefined

Instead of the general variable:

JS Code
    1. var x = 1;
    2. Delete x; False
    3. X 1

or a function:

JS Code
    1. function X () {}
    2. Delete x; False
    3. typeof X; "Function"

Note Delete will return false only if it cannot be deleted.

To understand this, we have to explain some of the basic concepts of variable initialization and variable properties-Unfortunately, few JavaScript books can talk about it. You can skip this section if you only want to know what it is but not what it is.

Type of code

In ECMAScript, there are three types of executable code: Global Code, function code, eval code.

1. When a piece of code is run as a program segment, it is executed under the global scope, which is the global code. In a browser environment, the <SCRIPT> element is usually a piece of global code.

2. All the code declared in function is the code of the functions, the most common is the response event of the HTML element (<p onclick= "..." >).

3. The code snippet passed into the built-in eval function is called the Eval code, and we'll see this type of uniqueness later.

Execution contexts (execution context)

There is always a context for execution when the ECMAScript code executes. This is a more abstract concept, but it can help us understand the scope and the related process of variable initialization. For the above three types of code snippets, there is a corresponding execution context, such as function code has a function context, global code has a global context, and so on.

The logical execution context can form a stack between each other, at the beginning of the global code execution there is a global context, when a function is called into the context of the corresponding function, and then can continue to invoke other functions or recursively call themselves, the execution context is nested similar to the function call stack.

Activation Object/variable Object

Each execution context is associated with a variable object, which is an abstract concept that allows us to understand the variable instantiation mechanism: The variables and methods declared in the source code are actually added as attributes to the object associated with the current context. .

When executing global code, Variable object is a global object, meaning that all global variables and functions exist as attributes of the variable.

JS Code
    1. /* In the Global environment, this is what this global object is pointing to */
    2. var global_object = this;
    3. var foo = 1;
    4. Global_object.foo; 1
    5. foo = = Global_object.foo; True
    6. function bar () {}
    7. typeof Global_object.bar; "Function"
    8. Global_object.bar = = = Bar; True

So what about the variables declared in the function? The situation is similar, the variable declared in the function is also the property of the corresponding context object, the only difference is that in the function code snippet, this object is called Activation object. A new active object is created each time a function call is entered.

In a function segment, not only the explicitly declared variables and functions become the properties of the active object, but the arguments object (the argument list of the function) that is implicitly present in each function is the same. Note that the active object is actually an internal mechanism, and the program code is inaccessible.

JS Code
    1. (function (foo) {  
    2.   
    3.   var bar =  2;  
    4.   function baz () {}  
    5.   
    6.    /* 
    7.    Yes, the active object is an abstract existence, and the default arguments object and the passed parameters are automatically set as the properties of the active object when each function is entered:   
    8.     activation_object.arguments; // arguments variable  
    9. &NBSP
    10.    incoming parameter foo: 
    11.     ACTIVATION_OBJECT.foo; //  1 
    12.  
    13.      variables declared within functions bar: 
    14.      activation_object.bar; // 2 
    15.  
    16.      and BAZ functions defined within the function:  
    17.     typeof ACTIVATION_OBJECT.baz; //  "function" &NBSP;
    18.   */  
    19.   
    20. }) (1);   

Finally, the variables defined in the EVEL code snippet are added to the context object that is currently executing eval, which means that when the Eval code is entered, it does not create a new variable object, but instead inherits the current environment.

JS Code
    1. var global_object = this;
    2. /* Foo is added to the current variable object, which is the global object. */
    3. Eval (' var foo = 1; ');
    4. Global_object.foo; 1
    5. (function () {
    6. /* Bar is added to the active object of the current function. */
    7. Eval (' var bar = 1; ');
    8. /*
    9. can be represented abstractly as:
    10. Activation_object.bar; 1
    11. */
    12. })();

Tags for variable properties

We already know what happens when we declare variables (they all become properties of the current context object), and then we'll look at what the properties are all about. Each variable property can have any of the following properties: ReadOnly, Dontenum, Dontdelete, Internal. You can take these as markers, indicating some of the attributes that a variable attribute can hold. What we are most interested in here is the dontdelete tag.

When declaring variables or functions, they all become properties of the current context object-the active object for the function code, the variable object for the global code, and it is worth noting that these properties are created with the dontdelete tag. However, an explicit or implicit assignment statement produces a property that does not have this tag! This is why there are some attributes we can delete, but others cannot:

JS Code
  1. var global_object = this;
  2. /* Foo is normally declared, so it is marked with dontdelete so it cannot be deleted! */
  3. var foo = 1;
  4. Delete foo; False
  5. typeof Foo; "Number"
  6. /* Bar is declared as a function, as with dontdelete, cannot be deleted. */
  7. function bar () {}
  8. Delete bar; False
  9. typeof Bar; "Function"
  10. /* Baz is directly through an assignment without declaring that it will not hold the dontdelete tag before it can be deleted! */
  11. Global_object.baz = ' blah ';
  12. Delete Global_object.baz; True
  13. typeof Global_object.baz; "Undefined"

Built-in objects and Dontdelete

A dontdelete is a special token that indicates whether a property can be deleted. It is important to note that some of the built-in objects are automatically held by this tag and cannot be deleted, such as the arguments within the function, and the length property of the function.

JS Code
    1. (function () {
    2. The/*arguments object holds the Dontdelete tag by default and cannot be deleted. */
    3. Delete arguments; False
    4. typeof arguments; "Object"
    5. /* The Length property of the function is also the same */
    6. function f () {}
    7. Delete f.length; False
    8. typeof F.length; "Number"
    9. })();

The incoming parameters of the function are the same:

JS Code
    1. (Function (foo, bar) {
    2. Delete foo; False
    3. Foo 1
    4. Delete bar; False
    5. Bar ' Blah '
    6. }) (1, ' blah ');

non-declarative assignment

As you might know, a non-declarative assignment statement produces a global variable that becomes the property of the global variable object. Therefore, according to the above explanation, non-declarative assignment of the resulting object can be deleted:

JS Code
    1. var global_object = this;
    2. /* Global variables declared will hold dontdelete and cannot be deleted. */
    3. var foo = 1;
    4. /* The variable assignment without a declaration is not dontdelete and can be deleted. */
    5. bar = 2;
    6. Delete foo; False
    7. typeof Foo; "Number"
    8. Delete bar; True
    9. typeof Bar; "Undefined"

It is important to note that attribute tags such as dontdelete are generated when this property is created , and any assignment to that property will not change the tag of this property!

JS Code
    1. /* Foo is declared with Dontdelete flag */
    2. function foo () {}
    3. /* After the assignment to Foo cannot change the mark he brings! */
    4. foo = 1;
    5. Delete foo; False
    6. typeof Foo; "Number"
    7. /* When assigning a value to a property that does not exist, a property with no tags (including dontdelete) is created and can be deleted! */
    8. This.bar = 1;
    9. Delete bar; True
    10. typeof Bar; "Undefined"

2. Firebug's Obsession

Now let's go back to the beginning of the question, why the variables declared in the Firebug console can be deleted? This involves the special behavior of the Eval code snippet, which is that the variable declared in eval is created without the dontdelete tag!

JS Code
    1. Eval (' var foo = 1; ');
    2. Foo 1
    3. Delete foo; True
    4. typeof Foo; "Undefined"

The same is true inside the function:

JS Code
    1. (function () {
    2. Eval (' var foo = 1; ');
    3. Foo 1
    4. Delete foo; True
    5. typeof Foo; "Undefined"
    6. })();

This is the culprit that leads to Firebug's "weird" behavior: The code in the Firebug console will eventually be executed through Eval, not as a global code or function code. Obviously, such declared variables are not tagged with dontdelete, so they can be deleted! (Translator: I can't trust firebug too much.) )

3. Browsers Compliance

Translator: This section of the mainstream browser to some of the special circumstances of the delete processing, the space is limited to temporarily do not repeat, interested can see the original.

4. IE bugs

Yes, you're right, this whole section is about IE's bug!.

In Ie6-8, the following code throws an error (Global code):

JS Code
    1. this.x = 1;
    2. Delete x; Typeerror:object doesn ' t support this action
    3. var x = 1;
    4. Delete this.x; Typeerror:cannot Delete ' this.x '

It seems that variable declarations in IE do not produce corresponding properties in global variable objects. It is also more interesting that the properties of an explicit assignment always go wrong on deletion, not really throwing an error, but rather that these properties appear to have dontdelete tags, contrary to our assumptions.

JS Code
    1. this.x = 1;
    2. Delete this.x; Typeerror:object doesn ' t support this action
    3. typeof X; "Number" (not deleted!) )
    4. Delete x; Typeerror:object doesn ' t support this action
    5. typeof X; "Number" (Still not deleted!) )

But the following code shows that a non-declarative assignment produces a property that can actually be deleted:

JS Code
    1. x = 1;
    2. Delete x; True
    3. typeof X; "Undefined"

But when you try to access x through the global variable object this, the error comes back:

JS Code
    1. x = 1;
    2. Delete this.x; Typeerror:cannot Delete ' this.x '

All in all, deleting an attribute with the global this variable (delete this.x) always goes wrong, while deleting the property (delete x): If x is generated by the global this assignment (this.x=1) causes an error, if X is created by an explicit declaration (Var x=1) Delete will not delete and return false, as we expected, and delete can be deleted normally if X is created with a non-declarative assignment (x=1).

One explanation for Garrett Smith is that "the global variable object of IE is implemented through JScript, and the general global variables are implemented by host." (Ref:eric Lippert ' s blog entry)

We can verify this explanation ourselves, notice that this and window appear to point to the same object, but the variable object of the current environment returned by the function is different from this one.

JS Code
    1. /* in Global code */
    2. function GetBase () {return this;}
    3. GetBase () = = = This.getbase (); False
    4. This.getbase () = = = This.getbase (); True
    5. Window.getbase () = = = This.getbase (); True
    6. Window.getbase () = = = GetBase (); False

5. Wrong understanding

Translator: The effect of the Internet on some of the JavaScript behavior has a variety of different interpretations, and some may even be completely contradictory, do not easily believe the explanation of others, try to find the core of the problem yourself:)

6. Delete and host object (host objects)

The approximate algorithm for delete is as follows:

1. Returns true if the action object is not a reference

2. Returns true if the current context object does not have a direct property of this name (the context object can be a global object or an active object within a function)

3. If such a property exists but has a dontdelete tag, returns false

4. In other cases, delete the property and return True

However, with one exception, the result of the delete operation is unpredictable for the host object. This is not surprising, because the host object allows different behavior depending on the implementation of the browser, which includes the delete. So when the host object is processed, the result is not credible, such as under FF:

JS Code
    1. /* "Alert" is a property of the Window object */
    2. Window.hasownproperty (' alert '); True
    3. Delete Window.alert; True
    4. typeof Window.alert; "Function", which indicates that there is actually no real deletion

In a word, don't trust the host object at any time.

7. ES5 Strict mode

In order to be able to find some problems that should be discovered earlier, ECMAScript 5th Edition proposed the concept of strict mode. Here is an example:

JS Code
  1. (function (foo) {
  2. "Use strict"; Enable strict mode within this function
  3. var bar;
  4. function Baz () {}
  5. Delete foo; SyntaxError (when deleting argument)
  6. Delete bar; SyntaxError (when deleting variable)
  7. Delete Baz; SyntaxError (when deleting variable created with function declaration)
  8. /* ' length ' of function instances has {[[configurable]]: false} */
  9. Delete (function () {}). length; TypeError
  10. })();

To delete a variable that does not exist:

JS Code
    1. "Use strict";
    2. Delete i_dont_exist; SyntaxError

To assign a value to an undeclared variable:

JS Code
    1. "Use strict";
    2. I_dont_exist = 1; Referenceerror

As you can see, strict mode takes a more proactive and descriptive approach, rather than simply ignoring invalid delete operations.

8. Summary

    • The Declaration of variables and functions will actually be the properties of the global object or the active object of the current function.
    • Property has a Dontdelete tag that indicates whether the property can be deleted.
    • The declarations of variables and functions are created with dontdelete tags.
    • The arguments object built into the function acts as the default property of the function's active object, and is always created with the dontdelete tag.
    • The variables and methods declared in the eval code block do not have a dontdelete tag.
    • Objects that are directly assigned to a variable or property that does not already exist do not have any markup, including Dontdelete.
    • The result of a delete operation can be unpredictable for a host object.

If you would like to know more about these, please refer to the ECMA Specification: ECMA-262 3rd Edition Specification

Original:

http://m.oschina.net/blog/28926

[Go] deep into the JavaScript delete operator

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.