SoFunction
Updated on 2025-03-01

Detailed explanation of using delete in javascript

In this article, the author starts with the errors about delete in the book "JavaScript Object-Oriented Programming Guide", and explains in detail the implementation of delete operations, limitations and manifestations in different browsers and plug-ins (here refers to firebug).

The main parts are translated below.

...The book claims

"A function is like a normal variable - it can be copied to different variables and even deleted."

The following code snippet is attached as an explanation:

Copy the codeThe code is 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 clip? The problem is that the operation of deleting the sum variable should not be successful; the declaration of delete should not return true and typeof sum should not be returned as undefined. Because, variables cannot be deleted in JavaScript, at least they cannot declare deletion in this way.

So what happened to this example? Is it a print error or a joke? Probably not. This snippet is an actual output in the firebug console, and Stoyan (the author of the book mentioned above) should be using it for a quick test. This seems to indicate that firebug has some different deletion rules. It was firebug that mislead Stoyan! So what's 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. Let me try to explain the details in this regard. We will realize that it is not actually “strange” by observing the “strange” behavior of firebug; we will dig deeper into the details behind it when we declare variables, functions, assign attributes and delete them; we will look at the browser's implementation of this and some famous bugs; we will also discuss the strict mode in ECMAScript version 5 and how it changes the behavior of the delete operator.

The Javascript and ECMPScript I used alternately below generally refer to ECMAScript (unless when it comes to Mozilla's JavaScript™ implementation explicitly).

As expected, there are very few explanations for delete on the Internet (author’s note: This article was written in January 2010). MDC(MDN]) The resource is probably the most detailed of this, but unfortunately it misses some interesting details, including the strange manifestation of the above firebug.MSDNDocumentation is almost useless.

1. Theory | Theory
So, why can we delete the properties of an object:

Copy the codeThe code is as follows:

var x = { a: 1 };
delete ; // true
; // undefined


But you cannot delete a variable:
Copy the codeThe code is as follows:

var x = 1;
delete x; // false;
x; // 1

You cannot delete a function:
Copy the codeThe code is 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 and property attributes (translator's note: For the difference between property and attributes, see the reference article, which is translated into internal attributes based on the content involved below) - These are rarely mentioned in JavaScript books. In the following paragraphs I will try to review these briefly, and it is not difficult to understand them. If you are not paying attention to 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 Global code
2. Function code Function code
code

The meaning of these categories is roughly like they are named, but let’s review it quickly:

1. When a source file is regarded as a program, it is executed within the scope, and this is considered a piece of global code. In a browser environment, the contents of the SCRIPT element are usually parsed into a program and are therefore executed as global code.

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

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

1.2. Context of code execution | Execution Context
When ECMAScript code is executed, it always occurs in a definite execution context. An execution scope is an abstract entity that helps understand how scope and variable instantiation work. The above three types of executable code have their own execution context. When the function code is executed, we say that the control side enters the execution context of the function code; when the global code is executed, we say that the control side enters the execution context of the global code, and so on.

As you can see, the execution context is logically a stack. First of all, there may be a piece of global code that has its own execution context; in this piece of code, a function may be called, and this function also has its own execution context; this function may call another function, etc. Even when the function calls itself recursively, a different execution context is still entered in each step of the call.

1.3. Activation object and variable object | Activation object / Variable object
Each execution context has a Variable object associated with it. Similar to it, a variable object is also an abstract entity, a mechanism used to describe variable instantiation. Interestingly, variables and functions declared in a piece of source code are actually added to the variable object as properties of the variable object.

When control enters the execution context of the 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 the codeThe code is 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 global variables become properties of global functions, so what about local variables - those variables declared in function code? In fact, that's simple: they also become properties of variable objects. The only difference is that in function code, the variable object is not a global object, but an Activation object we call. A revitalized object is created every time you enter the execution context of the function code.

It is not only variables and functions declared in function code that become properties of the activated object: each actual argument (arguments, with the name of the corresponding formal argument as the attribute name), and a special Arguments object (arguments as the attribute name) also become properties of the activated object. It should be noted that the activation object, as an internal mechanism, cannot actually be accessed by program code.

Copy the codeThe code is 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 where it is located:
        ACTIVATION_OBJECT.arguments = arguments;
...The same is true for parameter 'foo':
        ACTIVATION_OBJECT.foo; // 1
...The same is true for variable 'bar':
        ACTIVATION_OBJECT.bar; // 2
...The same is true for the function 'baz':
        typeof ACTIVATION_OBJECT.baz; // "function"
      */
}) (1);

Finally, the variable declared in Eval code becomes the property of the context's Variable object. Eval code simply uses variable objects in the execution context in its call.

Copy the codeThe code is as follows:

var GLOBAL_OBJECT = this;
eval('var foo = 1');
GLOBAL_OBJECT.foo; // 1;

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

    /*
In the process of abstraction
        ACTIVATION_OBJECT.bar; // 2
    */
}) ();

1.4. Internal properties of properties | Property attributes
It's about to get closer to the topic. Now that we have clarified what happens to variables (they become properties), the remaining concept to be understood is the property attributes of the attributes. Each property has zero to multiple internal properties such as *ReadOnly, DontEnum, DontDelete and Internal**. You can think of them as labels—a property may or may not have some special internal property. In today's discussion, we are interested in DontDelete.

When variables and functions are declared, they become properties of variable objects—either activated objects (in function code) or global objects (in global code)—those attributes are generated with the internal attribute DontDelete. However, any explicit/implicit assignment attributes do not generate DontDelete. And this is essentially why we can delete some properties but not others.

Copy the codeThe code is as follows:

var GLOBAL_OBJECT = this;

/* 'foo' is a property of the global object.
It is generated by variable declaration, so it has the internal property 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 variable declaration, so it has DontDelete sub
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 attribute assignment, so there is no DontDelete
That's why it can be deleted*/
GLOBAL_OBJECT.baz = "baz";
delete GLOBAL_OBJECT.baz; // true
typeof GLOBAL_OBJECT.baz; // "undefined"

1.5. Build-ins and DontDelete

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

Copy the codeThe code is as follows:

(function() {
//Cannot delete 'arguments' because there is DontDelete
    delete arguments; // false;
    typeof arguments; // "object"

//The length of the function cannot be deleted, because there is DontDelete
    function f() {};
    delete ; // false;
    typeof ; // "number"
}) ();

The attributes associated with the function arguments also have DontDelete and cannot be deleted.

Copy the codeThe code is as follows:

(function(foo,bar) {
    delete foo; // false
    foo; // 1

    delete bar; // false
    bar; // "bah"
}) (1,"bah");

1.6. Undeclared assignments | Undeclared assignments
You may remember that undeclared variable assignments become attributes of the global object unless this attribute is found elsewhere in the scope chain. Now we understand the difference between attribute assignment and variable declaration - the latter generates DontDelete while the former does not generate - this is why undeclared variable assignments can be deleted.

Copy the codeThe code is as follows:

var GLOBAL_OBJECT = this;

/* Generate the properties of the global object through variable declaration, own DontDelete */
var foo = 1;

/* Generate properties of the global object through undeclared variable assignment, without DontDelete */
bar = 2;

delete foo; // false
delete bar; // true
Note: Internal attributes are determined when attribute generation, and subsequent assignment process will not change the internal attributes of existing attributes. It is important to understand this difference.

/* 'foo' is created and generated at the same time */
function foo() {};

/* The subsequent assignment process does not change the internal properties of the existing properties, DontDelete still exists */
foo = 1;
delete foo; // false;
typeof foo; // "number"

/* But when assigning a non-existent property, a property without internal properties is created, so there is no DontDelete */
= 1;
delete bar; // true;
typeof bar; // "undefined"

2. Firebug confusion | Firebug confusion

So, what's happening in firebug? Why can variables declared in the console be deleted, rather than as we discussed earlier? I've said before that Eval code has a special behavior when it handles variable declarations: variables declared in Eval code actually generate a property without DontDelete.

Copy the codeThe code is as follows:

eval('var foo = 1;');
foo; // 1
delete foo; // true
typeof foo; // "undefined"

The same is true in function code:

Copy the codeThe code is as follows:

(function() {
    eval('var foo = 1;');
    foo; // 1
    delete foo; // true
    typeof foo; // "undefined"
}) ();

And this is the reason for abnormal behavior in Firebug. All debug text in the console seems to be compiled and executed in Eval code, not in global or function code. Obviously, all variable declarations in it eventually generate attributes without DontDelete, so they can be deleted. So be careful about the difference between ordinary global code and code in Firebug console.

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 delete attributes that could not have been deleted. This aspect is about function declarations—they can override variables with the same name in the same execution context:

Copy the codeThe code is as follows:

function x() { };
var x;
typeof x; // “function”

So why does a function declaration have priority and can override a variable with the same name (or in other words, the same properties of a variable object (Variable object)? This is because the instantiation process of function declarations is after variable declarations, so they can be overwritten.

(Translator's note: Function declaration can only overwrite variables of the same name that are declared but not assigned. If a value is assigned during declaration (. var x = 1), the process of assigning value will be overwritten by variable assignment after the function is initialized, the function declaration will be overwritten by variable assignment, as follows:)

Copy the codeThe code is as follows:

var x = 1;
function x() { };
typeof x; // "number"

The function declaration not only replaces the value of the property, but also replaces its internal properties. If we declare a function through eval, this function will also replace the previous one with its own internal properties. Since the attribute generated by the variable declared in eval does not have DontDelete, instantiating this function will "theoretically" remove the existing DontDelete internal attribute of the original attribute, making this attribute deleteable (of course, it also points the value to the newly generated function).

Copy the codeThe code is as follows:

var x = 1;
/* Cannot be deleted, ‘x’ has DontDelete*/
delete x; // false
typeof x; // "number"

eval('function x() { }');
/* property 'x' now points to the function and should not have DontDelete */
typeof x; // "function"
delete x; // It should be ‘true’;
typeof x; // should be "undefined"

Unfortunately, this trick has not succeeded in every browser I tried. I might have missed something here, or the behavior is so hidden that various browsers don't notice it.

(Translator's note: The problem here may be that the override between function declaration and variable declaration is only a change in the value pointing, while the internal property DontDelete is determined at the initial declaration and no longer changes, and the variables and functions declared in eval are only deleted in the external context that are not declared in its external context. Regarding the execution order, since eval is a function, its call is always after other variables and function declarations in its external context, so the relevant internal properties have also been determined, and the override is only the pointing of the value. As follows:)

Copy the codeThe code is as follows:

/* The first alert returns "undefined" because the assignment process is after the declaration process and the eval execution process;
The second alert returns "false", because although the location of x declared after eval,
However, the execution of eval is after the variable declaration, so it cannot be deleted */
eval(' alert( x ); alert(delete x) ');
var x = 1;

3. Browsers compliance | Browsers compliance

It is important to understand how things work, but the actual implementation is even more important. Do browsers comply with these standards when creating and deleting variables/attributes? For most, yes.

I wrote oneSimple test unitTo check the compliance of global code, function code and Eval code. The test unit also detects whether the return value and attribute of the delete operation are deleted as expected. The return value of delete is not as important as its actual result. It is not important for the delete operation to return true or false, it is important whether the attribute with/without DontDelete is deleted.

Modern browsers generally follow the deletion rules. All the following browsers have passed the test: Opera 7.54+, Firefox 1.0+, Safari 3.1.2+, Chrome 4+.

There is a problem with Safari and 3.0.4 when deleting the function arguments, it seems that these properties do not have DontDelete when created and can therefore be deleted. Safari has other problems - an error is thrown when deleting no references (such as delete 1) (Translator's note: IE also has); a function declaration generates deleteable properties (strangely, variable declarations are normal); a variable declaration in eval becomes undelete (while the function declaration in eval is normal).

Similar to Safari, Konqueror (3.5, not 4.3) has the same problem with no references and delete arguments in delete.

3.1、Gecko DontDelete bug
Gecko 1. Browser - Firefox , Camino , Seamonkey , etc. - There is an interesting bug: explicit assignment of values ​​to a property that can remove its DontDelete, even if the property is generated by a variable or function declaration.

Copy the codeThe code is as follows:

function foo() { };
delete foo; // false;
typeof foo; // "function"

= 1;
delete foo; // true
typeof foo; // "undefined"

Surprisingly, IE5.5-8 also passed most of the tests, except for removing non-reference throwing errors (. delete 1, like the old Safari). However, although it cannot be discovered immediately, in fact, there are more serious bugs in IE, which are about global objects.

IV. IE bugs

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

Copy the codeThe code is as follows:

= 1;
delete x; // TypeError: Object doesn't support this action

And the following is another:

Copy the codeThe code is as follows:

var x =1;
delete ; // TypeError: Cannot delete ''
// Translator's note: This exception is thrown in IE8, and the same exception as above is thrown in IE6 and 7.

This seems to indicate that variable declarations in the global code in IE do not generate properties of the same name for the global object. An attribute created by assignment ( = 1) and then throws an exception when deleted by delete x; an attribute created by variable declaration (var x = 1) and then throws another when deleted by delete (Translator's note: The error message is the same as above under IE6,7).

But not just that, in fact, attributes created by explicit assignments always throw exceptions when deleted. This is not just a mistake, but the created property looks like it has the DontDelete internal properties, which should not be by rule:

Copy the codeThe code is as follows:

= 1;
delete ; // TypeError: Object doesn't support this action
delete x; // TypeError: Object doesn't support this action

On the other hand, undeclared variable assignments (the properties that also generate global objects) can indeed be deleted normally under IE:

Copy the codeThe code is as follows:

x = 1;
delete x; // true

But if you try to delete (delete) through this keyword, the above exception will be thrown again:

Copy the codeThe code is as follows:

x = 1;
delete ; //TypeError: Cannot delete ''

If we summarize it, we will find that 'delete' in global code will never succeed. A exception is thrown when an attribute is generated by explicit assignment (=1); another exception is thrown when an attribute is generated by declaring/nondeclaring variables (var x = 1 or x = 1). On the other hand, delete x only throws an exception when displaying the assignment generating attribute (= 1).

existI discussed this issue in September,inGarrett SmithIt is believed that in IE, the global variable object is implemented as a JScript object, while the global object is implemented by the host object.

We can confirm this theory to some extent through several tests. Note that this and window seem to refer to the same object (if the ‘===’ operator can be trusted), while the variable object Variable object (the basis of function declaration) is different from the references to this.

Copy the codeThe code is as follows:

function getBase() { return this; };

getBase() === (); // false
() === (); // true
() === (); // true
() === getBase(); // false

5. Misconceptions | Misconceptions

We cannot underestimate the importance of understanding how things work. I've seen some misunderstandings about delete operations on the Internet. For example,An answer on *(And the level is still very high), it explains that "delete is supposed to be no-op when target isn't an object property". Now that we understand the core of the delete operation, we will understand that the answer is incorrect. delete does not distinguish between variables and attributes (in fact, these are references in delete operations), but only cares about DontDelete (and whether the attribute already exists).

6. 'delete' and host object | 'delete' and host object

A delete algorithm looks like this:

1. If the operator is not a reference, return true
2. If the object does not have a **direct attribute** of the same name, return true (as we know, the object can be a global object or an activated object)
3. If the property already exists but has DontDelete, return false
4. Otherwise, remove the remove attribute and return true
However, the behavior of the delete operation for the host object may be unpredictable. In fact, this is not wrong: the host object (through certain rules) allows any operation to be implemented, such as reading (internal [[Get]] method), writing (internal [[Write]] method), deleting (internal [[Delete]] method), etc. This allows custom [[Delete]] behavior to cause confusion in the host object.

We have seen some problems in IE: exceptions are thrown when certain objects (those implementations are implemented for host objects) properties are deleted. Some versions of firefox throw exceptions when trying to delete (translator's note: IE also throws). Similarly, in some host objects you cannot believe the return value of delete, for example, the following happens in firefox (Translator's note: the same result in chrome; exceptions are thrown in IE; operator and safari allow deletion, and cannot be called after deletion, so it is considered 'normal', although from the following discussion, it seems abnormal, they actually delete attributes that cannot be deleted, but the previous browser does not):

Copy the codeThe code is as follows:

/* 'alert' is a direct property of 'window' (if we can believe 'hasOwnProperty') */
('alert'); // true

delete ; // true
typeof ; // "function"

delete returns true, although there is no condition for this property to produce this result (according to the above algorithm): it resolves to a reference, so it cannot return true in the first step; it is a direct property of the window object, so it cannot return true in the second step; the only thing that can return true is that when the algorithm reaches the last step, it does delete the property, but in fact it is not deleted. (Translator's note: No, it was indeed deleted in opera and safari...).

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

7. ES5 strict mode | ES5 strict mode

So what will the strict mode in ECMAScript version 5 bring? Some of these limitations are currently introduced. A SyntaxError is thrown when the delete operation points to a direct reference to a variable/function parameter/function declaration. Additionally, if the property has an internal property [[Configurable]] == false, a TypeError will be thrown:

Copy the codeThe code is as follows:

(function(foo) {
"use strict"; //Enable strict mode in the function

    var bar;
    function baz;
delete foo; // SyntaxError, when deleting function parameters
delete bar; // SyntaxError, when deleting variables
delete baz; // SyntaxError, when deleting variables created by function declaration

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

Moreover, in strict mode, delete undeclared variables (in other words, unresolved references) and throw a SyntaxError; similarly, undeclared assignments in the same mode will also throw an exception (ReferenceError)

Copy the codeThe code is as follows:

"use strict";
delete i_dont_exist; // SyntaxError
i_dont_exist_either = 1; // ReferenceError

After looking at the examples of variables, function declarations and parameters given before, I believe that now you understand that all these limitations have their meaning. The strict model takes more positive and descriptive measures, rather than just ignoring these issues.

8. Summary | Summary

Since this post is already very long, I will not discuss anything else (.Delete array items and their effects via delete). You can readArticles on MDC/MDNOr read the specification and test it yourself.

Here is a simple summary of how delete works in Javascript:

•Variable and function declarations are properties of activation global objects.
•Attributes have internal properties, one of which - DontDelete is responsible for determining whether an attribute can be deleted.
•Variables and function declarations in global code or function code generate attributes that have DontDelete.
• Function parameters are also properties of the activation object and also have DontDelete.
•Neither variables and function declarations in the Eval code generate properties without DontDelete.
•The new undeclared property has an empty internal property when generated, so there is no DontDelete either.
•Host objects allow response to the deletion process in any way they expect.

original:Understanding deleteTranslation:delete in javascriptTranslator:justjavac