Delete in JavaScript using the _javascript tips

Source: Internet
Author: User
Tags getbase hasownproperty

In this article, the author starts with the error about delete in the JavaScript object-oriented Programming Guide, detailing the implementation of the delete operation, limitations, and performance in different browsers and Plug-ins (refer to Firebug).

The following translation of the main parts.

... The book says

"The function is like a normal variable--it can be copied to a different variable or even deleted."

The following code fragment is attached as a description:

Copy Code code as follows:

>>> var sum = function (A, b) {return a+b;};
>>> var add = sum;
>>> delete sum;
True
>>> typeof sum;
"Undefined"

Can you find the problem in the fragment? The problem is that the operation to delete the sum variable should not succeed; the declaration of delete should not return true and typeof sum should not return to undefined. Because a variable cannot be deleted in JavaScript, at least it cannot be declared in this way.

So what happened with this example? Is it a print error or a joke? I don't think so. This fragment is an actual output from the Firebug console, and Stoyan (the author of the story above) should be the quick test that it does. This seems to indicate that Firebug has some different deletion rules. It was Firebug who misled stoyan!. So what is going on here?

To answer this question, we need to understand how the delete operator works in Javascript: which can be deleted, which cannot be deleted, and why. I'll try to explain the details here. By observing the "strange" manifestations of firebug, we realize that it is in fact not "strange" at all; we'll delve into those details that are hidden behind when we declare variables, functions, assign attributes, and delete them; we'll look at the browser's implementation of this and some well-known bugs; We also discuss the rigorous mode (strict mode) in ECMAScript version 5 and how it changes the behavior of the delete operator.

The Javascript and ecmpscript I use interchangeably below are generally referred to as ECMAScript (unless the JavaScript™ implementation of Mozilla is explicitly mentioned).

Unsurprisingly, there are very few explanations for delete on the Web (I press: This article was written in January 2010). The MDC (MDN) resource is probably the most detailed of these, but unfortunately it misses out some interesting details that include the firebug of the above. The MSDN documentation is of little use.

I. Theory | Theory
So, why can we delete an object's properties:

Copy Code code as follows:

var x = {a:1};
Delete x.a; True
X.A; Undefined


But you cannot delete a variable:
Copy Code code as follows:

var x = 1;
Delete x; False
X 1

You cannot delete a function:
Copy Code code as follows:

function X () {};
Delete x; False
typeof X; "Function"

Note: Delete returns false only if a property cannot be deleted.

To understand this, we need to first grasp some concepts: variable instantiation (variable instantiation) and intrinsic properties (property attributes) (translator: About properties and attributes The difference is seen in the reference article, which is intended to be translated into internal attributes according to the content described below--these are rarely mentioned in JavaScript books. In the following paragraphs I will try to briefly review these elements, and it is not difficult to understand them. If you are not concerned about the reasons behind their performance, you can skip this chapter.

1.1, type of code | Type of code

There are three types of executable code in ECMAScript:

1. Global Code
2. Function code
3.Eval Code

The meanings of these categories are roughly as they are named, but they are quickly reviewed:

1. When a source file is viewed as a program, it executes within the global scope (scope), which is considered to be a piece of global code. In a browser environment, the contents of a SCRIPT element are usually parsed into a program and thus executed as a global code.

2. Of course, any code that executes directly in a function is considered a function code, in the browser environment, the content of the event property (e.g). <a onclick= "..." is usually parsed and executed as a function code.

3. Finally, the code that puts the built-in function eval is parsed as an eval code. We will soon see why this type is special.

1.2, the context of the Code execution | Execution context
When the ECMAScript code executes, it always occurs in a determined execution context. The execution scope is an abstract entity that helps to understand how scopes and variable instantiations work. The above three types of executable code have their own execution context. When the function code executes, we say that the control end goes into the execution context of the function code, and when the global code executes, we say that the control end is in the execution contexts of the global code, and so on.

As you can see, the execution context is logically one stack (stack). First there may be a piece of global code, which has its own execution context, where a function may be called, which also has its own execution context, which may call another function, and so on. Even when a function recursively calls itself, it still enters a different execution context in each step of the call.

1.3. Activating objects and Variable objects | Activation Object/variable Object
Each execution context has a variable object (Variable object) associated with it. Like it, a variable object is also an abstract entity, a mechanism for describing variable instantiation. Interestingly, variables and functions declared in a section of the source code are actually added to the variable object as properties of the variable object (Variable object).

When control enters the execution context of global code, a global object is used as a variable object. This is precisely why globally declared variables and functions become properties of a global object:

Copy Code code as follows:

var global_object = this;
var foo = 1;
Global_object.foo; 1
function bar () {};
typeof Global_object.bar; "Function"
Global_object.bar = = Bar; True

Ok, so the global variable becomes the property of the global function, so the local variables--What about the variables declared in the function code? In fact it's simple: they're also attributes of variable objects. The only difference is that in the function code, the variable object is not a global object, but rather an activation object (Activation object). An Activation object is created each time the execution context of the function code is entered.

The variables and functions declared in the function code are not the properties of the activated object: each argument of the function (arguments, the name of the corresponding formal parameter), and a special arguments object (arguments as the property name) Also becomes the property of the activation object. It should be noted that the activation object as an internal mechanism cannot in fact be accessed by program code.

Copy Code code as follows:

(function (foo) {
var bar = 2;
function Baz () {};
/*
In the process of abstraction,
The special ' arguments ' object becomes the property of the activated object of the function:
activation_object.arguments = arguments;
... The parameter ' foo ' is the same:
Activation_object.foo; 1
... The variable ' bar ' is the same:
Activation_object.bar; 2
... The function ' Baz ' is the same:
typeof Activation_object.baz; "Function"
*/
}) (1);

Finally, the variable declared in the Eval code becomes the property of the context's variable object (contexts ' s Variable object). Eval code simply uses the variable object in the execution context in which it is invoked.

Copy Code code as follows:

var global_object = this;
Eval (' var foo = 1 ');
Global_object.foo; 1;

(function () {
Eval (' var bar = 2 ');

/*
In the abstract process
Activation_object.bar; 2
*/
}) ();

1.4, properties of the internal properties | Property attributes
Close to the subject. Now that we have a clear idea of what is happening to the variables (they are attributes), the remaining concepts that need to be understood are the intrinsic properties (property attributes). Each property has 0 to multiple such as internal properties--*readonly,dontenum,dontdelete and internal**. You can think of them as tags--a property may or may not have a particular intrinsic attribute. In today's discussion, we are interested in dontdelete.

When declaring variables and functions, they become variable objects (Variable object)-Either the activation object (in the function code), or the properties of the global object (in global code), which are accompanied by the generation of internal property dontdelete. However, any explicitly/implicitly assigned property does not generate a dontdelete. And that's essentially why we can remove some of the attributes and not remove the other reason.

Copy Code code as follows:

var global_object = this;

/* ' foo ' is a property of the global object,
It is generated through variable declarations and therefore has internal properties Dontdelete
That's why it can't be deleted.
var foo = 1;
Delete foo; False
typeof Foo; "Number"

/* ' Bar ' is a property of the global object,
It is generated by a variable declaration and therefore owns the Dontdelete
That's why it can't be deleted too.
function bar () {};
Delete bar; False
typeof Bar; "Function"

/* ' Baz ' is also a property of the global object,
However, it is generated by assigning values to properties, so there is no dontdelete
That's why it can be removed.
Global_object.baz = "Baz";
Delete Global_object.baz; True
typeof Global_object.baz; "Undefined"

1.5. Built-in and Dontdelete | Build-ins and Dontdelete

So that's why all of this happens: a special internal property of a property controls whether the property can be deleted. Note: Some properties of the built-in object have internal property dontdelete and cannot be deleted, and special arguments variables (as we know, the properties of the activated object) have dontdelete; the length (return parameter lengths) property of any function instance has Dontdelete:

Copy Code code as follows:

(function () {
Cannot delete ' arguments ' because there are dontdelete
Delete arguments; False
typeof arguments; "Object"

You cannot delete the length of a function because there are dontdelete
function f () {};
Delete f.length; False
typeof F.length; "Number"
}) ();

Properties associated with the function arguments also have dontdelete and cannot be deleted

Copy Code code as follows:

(function (Foo,bar) {
Delete foo; False
Foo 1

Delete bar; False
Bar "Bah"
}) (1, "bah");

1.6, not declared variable assignment | Undeclared assignments
As you may recall, an undeclared variable assignment becomes a property of the global object, unless the property is found elsewhere in the scope chain. Now we understand the difference between attribute assignment and variable declaration-the latter generates Dontdelete and the former is not generated-which is why undeclared variable assignments can be deleted.

Copy Code code as follows:

var global_object = this;

/* The properties of the global object are generated by a variable declaration, with Dontdelete * *
var foo = 1;

/* Create properties of global objects by assigning values to undeclared variables without dontdelete/
bar = 2;

Delete foo; False
Delete bar; True
Note: Internal properties are determined at property generation, and subsequent assignment procedures do not alter the intrinsic properties of an existing property. It is important to understand this distinction.

* * "Foo" created by the same time generate Dontdelete * *
function foo () {};

/* After the assignment process does not change the intrinsic properties of the existing attributes, Dontdelete still exists * *
foo = 1;
Delete foo; False
typeof Foo; "Number"

/* But when an attribute is assigned that does not exist, a property with no intrinsic property is created, so there is no dontdelete * *
This.bar = 1;
Delete bar; True
typeof Bar; "Undefined"

Second, the chaos of Firebug | Firebug confusion

So, what happened in Firebug? Why are the variables declared in the console able to be deleted instead of what we discussed earlier? As I said before, the Eval code has a special behavior when it handles variable declarations: variables declared in Eval code actually generate a property that has no dontdelete.

Copy Code code as follows:

Eval (' var foo = 1; ');
Foo 1
Delete foo; True
typeof Foo; "Undefined"

The same is true in the function code:

Copy Code code as follows:

(function () {
Eval (' var foo = 1; ');
Foo 1
Delete foo; True
typeof Foo; "Undefined"
}) ();

And this is the reason for the abnormal behavior in Firebug. All of the debug text in the console appears to be compiled and executed with Eval code, rather than in global or function code. Obviously, the variable declarations are eventually generated with no dontdelete attributes, so they can be deleted. So be careful with the difference between common global code and FIREBUG console code.

2.1. Delete Variables via eval | Delete variables via eval
This interesting eval behavior, combined with another aspect of ECMAScript, can technically allow us to remove attributes that could not otherwise be deleted. This aspect is about function declarations--they can overwrite variables of the same name in the same execution context:

Copy Code code as follows:

function X () {};
var x;
typeof X; "Function"

So why does a function declaration have precedence over a variable of the same name (or, in other words, the same property of a variable object (Variable))? This is because the instantiation of the function declaration is after the variable declaration, so you can overwrite them.

(Translator: A function declaration can only overwrite a variable with the same name as a declaration without assigning a value, if the value is assigned at the time of the Declaration (e.g). var x = 1 The procedure for assigning values is overridden by a variable assignment after the function has been initialized, as follows:

Copy Code code as follows:

var x = 1;
function X () {};
typeof X; "Number"

The function declaration replaces not only the value of the property, but also its internal properties. If we declare a function through Eval, this function will also replace the previous one with its own internal property. And because the variables that are declared in Eval do not have dontdelete, instantiating this function will "theoretically" remove the existing Dontdelete intrinsic properties of the original attribute, making it possible to delete the property (and, of course, point the value to the newly generated function).

Copy Code code as follows:

var x = 1;
/* Cannot delete, ' x ' has dontdelete*/
Delete x; False
typeof X; "Number"

Eval (' function X () {} ');
/* attribute ' X ' now points to function, and should not have dontdelete * *
typeof X; "Function"
Delete x; Should be ' true ';
typeof X; It's supposed to be "undefined."

Unfortunately, this deception technique was unsuccessful in every browser I tried. I might have missed something here, or the behavior was so subtle that browsers didn't notice it.

(Translator: The problem here may be: the overwrite between the function declaration and the variable declaration is only the change of the value point, while the internal property dontdelete is determined at the initial declaration and no longer changes, and the variables and functions declared in the eval can only be deleted if they are not declared in their external context. With regard to the order of execution, because Eval is a function, its invocation is always after the other variables and functions in its external context, so the related internal properties are also determined, overwriting only the point of the value. as follows:)

Copy Code code as follows:

/* The first alert returns "undefined" because the assignment procedure is after the declaration process and the eval execution process;
The second alert returns "false" because, although the position of the X declaration is after Eval,
But the eval execution was not deleted after the variable declaration.
Eval (' alert (x); alert (delete x) ');
var x = 1;

Third, the browser compliance | Browsers Compliance

It is important to understand how things work, but the actual implementation is more important. Does the browser follow these criteria when creating and deleting variables/attributes? For the most part, yes.

I wrote a simple test unit to check the compliance of global, functional, and eval codes. The test unit also detects whether the return value of the delete operation and the property are deleted as expected. The return value of the delete is not as important as its actual result, and it is not important that the delete operation return TRUE or FALSE, and it is important that the owning/no dontdelete attribute is deleted.

Modern browsers generally adhere to the deletion rules, the following browsers all passed the test: Opera 7.54+, Firefox 1.0+, Safari 3.1.2+, Chrome 4+.

Safari 2.x and 3.0.4 have problems deleting function arguments, and it appears that these properties are created without dontdelete and therefore can be deleted. Safari 2.x has other problems--throw errors when no references are removed (for example, delete 1) (translator: IE also has); the function declaration generates the properties that can be deleted (oddly, the variable declaration is normal); the variable declaration in Eval becomes not removable (and the function declaration in eval is normal).

Similar to Safari, Konqueror (3.5, not 4.3) has the same problem with deleting arguments without references and deletions.

3.1, Gecko Dontdelete bug
Gecko 1.8.x Browser--firefox 2.x, Camino 1.x, SeaMonkey 1.x, etc.--There is an interesting bug: an explicit assignment value gives an attribute the ability to remove its dontdelete, even if the property is generated by a variable or function declaration.

Copy Code code as follows:

function foo () {};
Delete foo; False
typeof Foo; "Function"

This.foo = 1;
Delete foo; True
typeof Foo; "Undefined"

Surprisingly, Ie5.5-8 also passed most of the tests, in addition to deleting unreferenced throw errors (e.g). Delete 1, just like old Safari. However, while it is not immediately discovered that IE has a more serious bug, these bugs are about global objects.

Four, IE bugs

In IE (at least in ie6-8), the following expression throws an exception (in global Code):

Copy Code code as follows:

this.x = 1;
Delete x; Typeerror:object doesn ' t support this action

And the following is another:

Copy Code code as follows:

var x = 1;
Delete this.x; Typeerror:cannot Delete ' this.x '
The translator presses: throws this exception under the IE8, throws under the ie6,7 is the same exception as above

This seems to indicate that in IE, variable declarations in global code do not generate a property with the same name as the global object. A property created by an assignment (This.x = 1) is then thrown with a delete x, and the property created by the variable declaration (var x = 1) is then thrown through the delete this.x (translator: The error message is the same as above in the ie6,7).

But not only that, in fact, properties created by an explicit assignment always throw an exception when deleted. This is not just a mistake, but a property that is created appears to have dontdelete intrinsic attributes that should not be available by rule:

Copy Code code as follows:

this.x = 1;
Delete this.x; Typeerror:object doesn ' t support this action
Delete x; Typeerror:object doesn ' t support this action

On the other hand, undeclared variable assignments (those that generate the same properties as global objects) can be deleted correctly under IE:

Copy Code code as follows:

x = 1;
Delete x; True

But if you attempt to delete by using the This keyword (delete this.x), the above exception is thrown:

Copy Code code as follows:

x = 1;
Delete this.x; Typeerror:cannot Delete ' this.x '

If summed up, we will find that in the global code ' delete This.x ' will never succeed. An exception is thrown when an attribute is generated by an explicit assignment (this.x = 1), and another exception is thrown when the property is generated by means of a declaration/Declaration variable (var x = 1 or x = 1). On the other hand, delete x throws an exception only if the assignment build property (this.x = 1) is displayed.

In September I discussed this issue, where Garrett Smith thought that the global variable object, the Global object, was implemented as a JScript object in IE, and that it was implemented by the host object.

We can confirm this theory in some way through several tests. Note that this and window seem to refer to the same object (if the ' = = = ' operator can be trusted), whereas the variable object Variable the object (the basis of the function declaration) is different from the this reference.

Copy Code code as follows:

function GetBase () {return this;};

GetBase () = = = This.getbase (); False
This.getbase () = = = This.getbase (); True
Window.getbase () = = = This.getbase (); True
Window.getbase () = = = GetBase (); False

V. Misunderstanding | Misconceptions

We cannot underestimate the importance of understanding the workings of things. I've seen some misconceptions about the delete operation on the web. For example, an answer (and a high level) on the StackOverflow explains that "delete is supposed to being no-op when target isn ' t". Now that we know the core of the delete operation, it is clear that the answer is incorrect. Delete does not differentiate between variables and attributes (in fact, these are references in the delete operation), but only the dontdelete (and whether the property already exists).

VI, ' delete ' and host Object | ' Delete ' and host object

The algorithm for a delete is roughly like this:

1. Returns true if the operand (operand) is not a reference
2. Returns true if the object does not have the * * Direct property of the same name (as we know, the object can be a global object or an active object)
3. Returns False if the property already exists but has Dontdelete
4. Otherwise, remove the removal property and return True
However, the behavior of the delete operation for host objects (host object) may be unpredictable. In fact this is not wrong: the host object (through a certain rule) allows any action to be implemented, such as reading (the internal [[get]] method), writing (The internal [[Write]] method), deleting (the internal [[[Delete]] method), and so on. This allows custom [[Delete]] behavior to cause confusion in the host object.

We've seen some problems with IE: throwing exceptions when you delete some objects (those that are implemented to host objects). Some versions of Firefox throw an exception when an attempt is made to delete the window.location (IE also throws the translator). Also, you can't trust the return value of deletes in some host objects, such as the following in Firefox: The same result in Chrome, the exception being thrown in IE, opera and Safari allowing deletion and the deletion of the call, which is ' normal ', though, This seems to be an anomaly from the following discussion, which actually removes the attributes that cannot be deleted, and the previous browser does not:

Copy Code code as follows:

/* ' alert ' is a direct attribute of ' window ' (if we can believe ' hasownproperty ') * *
Window.hasownproperty (' alert '); True

Delete Window.alert; True
typeof Window.alert; "Function"

The delete Window.alert returns True, although this property does not have any conditions that could produce this result (according to the above algorithm): it resolves to a reference and therefore cannot return true in the first step; it is a direct property of the Window object and therefore cannot return true in the second step; The only thing that returns true is that when the algorithm reaches the last step, it does delete the attribute, but it is not actually deleted. (Translator: No, in opera and Safari is really deleted ...) )。

So this story tells us never to trust the host object.

Seven, ES5 strict mode | ES5 Strict mode

So what will the rigorous model in the ECMAScript 5th edition bring? Some of these limitations are currently described. Throws a syntaxerror when a delete operation points to a direct reference to a variable/function argument/function declaration. In addition, if the property has an internal property [[[configurable]] = = False, the TypeError is thrown:

Copy Code code as follows:

(function (foo) {
"Use strict"; To open strict mode in a function

var bar;
function Baz;
Delete foo; SyntaxError, when you delete a function argument
Delete bar; SyntaxError, when you delete a variable
Delete Baz; SyntaxError, when you delete a variable created by a function declaration

/* The length of the function instance has [[configurable]]: false */
Delete (function () {}). length; TypeError
}) ();

Also, in strict mode, deleting an undeclared variable (in other words, an unresolved reference) also throws a syntaxerror; Similarly, an unspecified assignment in the same mode throws an exception (Referenceerror)

Copy Code code as follows:

"Use strict";
Delete i_dont_exist; SyntaxError
I_dont_exist_either = 1; Referenceerror

Looking at examples of variables, function declarations, and parameters given before, I believe you now understand that all of these limitations have meaning. Strict patterns take more aggressive and descriptive measures than simply ignoring them.

Viii. Summary | Summary

Since this article is already very long, I will not discuss anything else (e.g. deletes an array entry and its effects by deleting). You can flip through the articles on MDC/MDN or read the specs and test yourself.

Here's a simple summary of how delete works in Javascript:

• Variable and function declarations are properties of the activation (activation) Global object.
• Attributes have internal properties, where one--dontdelete is responsible for determining whether a property can be deleted.
• Variables, function declarations in global Code or function code generate properties that have dontdelete.
• Function parameters are also properties of the activated object and have dontdelete.
Variables and function declarations in eval code generate properties that do not have dontdelete.
• The new undeclared attribute is generated with an empty internal property, so there is no dontdelete.
• Host objects allow the deletion process to be responded to in any way they expect.

Original: Understanding Delete: Delete Translator in javascript: Justjavac

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.