Delete the key and javascriptobject in the middle of a Javascript Object
This is not the case either. Go back to farming and you will
Copy codeThe Code is as follows:
Delete thisIsObject [key]
Or
Delete thisIsObject. key
By the way, let's talk about the delete usage.
A few weeks ago, I had a chance to read Stoyan Stefanov's Object-Oriented Javascript book. this book has a high rating on Amazon (12 comments, 5 stars), so I'm curious to see if it is so worth recommending, so I began to read the chapter on functions. I really appreciate the way this book explains things. Examples are organized in a very beautiful and progressive way. It seems that even beginners can easily master this knowledge. however, almost immediately, I found an interesting misunderstanding throughout the chapter-deleting function functions. there are also some other errors (such as the difference between a function declaration and a function expression), but we will not discuss them at present.
This book claims:
"A function is treated as a normal variable-it can be copied to or even deleted from different variables". An example is added after this explanation:
Copy codeThe Code is as follows:
Var sum = function (a, B) {return a + B ;}
Var add = sum;
Delete sum
True
Typeof sum;
"Undefined"
Ignore some missing semicolons. Can you see the errors of these code statements? Obviously, the error is that the operation to delete the sum variable will not succeed. the delete expression should not return true, and the typeof sum should not return "undefined ". all of this is because it is impossible to delete variables in JavaScript. at least, this statement is not possible.
So what happened in this example? Is it an error? Or is it a special usage? Probably not. this piece of code is actually the real output in the Firebug console. Stoyan must have used it as a quick test tool. this is almost like Firebug following some other delete rules. it was Firebug that led Stoyan to go astray! So what happened here?
Before answering this question, we must first understand how the delete operator works in JavaScript: What can be deleted, and what cannot be deleted? Today, I will try to explain this question in detail. we will look at Firebug's "strange" behavior and realize that it is not that strange. we will have a deep understanding of what is hidden behind declaring variables, functions, assigning values to attributes, and deleting them. we will look at the browser compatibility and some of the most notorious bugs. we will also discuss the strict mode of ES5 and how it changes the behavior of the delete operator.
I will switch between using JavaScript and ECMAScript, both of which mean ECMAScript (unless explicitly speaking about Mozilla's JavaScript implementation)
As expected, the interpretation of delete on the network is quite scarce. MDC article is probably the most understandable resource, but unfortunately it lacks some interesting details about this topic. it is strange that one of the forgotten things is the reason for the strange performance of Firebug. the MSDN reference is almost useless in these aspects.
Theory
Why can we delete the attributes of an object:
Copy codeThe Code is as follows:
Var o = {x: 1 };
Delete o. x; // true
O. x; // undefined
But cannot delete objects declared as follows:
Copy codeThe Code is as follows:
Var x = 1;
Delete x; // false
X; // 1
Or the function:
Copy codeThe Code is as follows:
Function x (){}
Delete x; // false
Typeof x; // "function"
Note: When an attribute cannot be deleted, the delete operator returns only false.
To understand this, we need to first master these concepts about variable instances and attribute properties-these concepts are unfortunately rarely mentioned in JavaScript. I will try to review these concepts in the following paragraphs. these concepts are hard to understand! Skip this chapter if you don't care why these things work in this way.
Code Type:
ECMAScript has three different types of executable code: Global code, Function code, and Eval code ). these types are more or less self-explanatory in terms of names. Here is a brief introduction:
When a piece of source code is regarded as a Program, it will be executed in a Global environment and considered as a Global code ). in a browser environment, the content of the script element is often interpreted as a program and therefore executed as a global code.
Any code directly executed in a Function is obviously considered as a Function code ). in the browser, the content of the event property (such as <p onclick = ".... ">) is usually interpreted as function code.
Finally, the code text applied to the built-in function eval is interpreted as Eval code. Soon we will find out why this type is special.
Execution context ):
When ECMAScript code is executed, it usually occurs in a specific execution context. execution context is an abstract entity concept that helps you understand how a Scope and a Variable instantiation work. each of the three executable codes has an execution context. when a function is executed, we say "program control enters the execution context of the Function Code". When a global code is executed, the program control enters the execution context of the global code, and so on.
As you can see, the execution context can logically form a stack. first, there may be a piece of Global Code and its own execution context. Then this Code may call a function and carry the execution context of the function. this function can call another function, and so on. even if the function is called recursively, each call enters a new execution context.
Activation object/Variable Object ):
Each execution context has a so-called Variable Object associated with it ). similar to the execution context, a variable object is an abstract entity and a mechanism used to describe a variable instance. interestingly, variables and functions declared in the source code are usually added to this variable object as properties.
When a program enters the execution context of the Global code, a Global object is used as a variable object. this is why the declared global function variable becomes a global object attribute.
Copy codeThe Code is as follows:
/* Remember that 'eas' 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
Yes, so the global variables will become the attributes of the global object. But what happens to local variables (those defined in the function code? In fact, their behavior is very similar: they will become the properties of the Variable object. the only difference is that, in function code, a variable object is not a global object, but an activity object ). the activity object is created every time it enters the execution context of the function code.
Not only variables and functions declared in the function code will become the properties of the activity object, but also in each function parameter (corresponding to the formal parameter name) and a special Arguments object (named as arguments. note that the activity object is an internal description mechanism and cannot be accessed in the program code.
Copy codeThe Code is as follows:
(Function (foo ){
Var bar = 2;
Function baz (){}
/*
In abstract terms,
Special 'arguments' object becomes a property of ining 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, the variables declared in the Eval code will become the attributes of the calling context variable object. The Eval Code simply uses the variable object that calls the execution context of the Code.
Copy codeThe Code is as follows:
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
*/
})();
Property attributes)
We are almost already here. now that we know exactly what happened to variables (they become attributes), the only concept to be understood is property attributes. each attribute can have zero or more features. They are selected from the following sets: ReadOnly, DontEnum, DontDelete, and Internal. you can think of them as flags-a feature that can exist in or does not exist. for our discussion today, we are only interested in DontDelete.
When declared variables and functions become attributes of variable objects (or activity objects of function code, or global objects of Global Code, these attributes are created with the DontDelete feature. however, any explicit (or implicit) Attribute Value assignment will not contain the DontDelete attribute. this is why we can delete some attributes but cannot delete others.
Copy codeThe Code is as follows:
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"
Built-in object and DontDelete
Therefore, this is all about it (DontDelete): A special attribute, used to control whether this attribute can be deleted. note that some built-in object attributes contain DontDelete, so they cannot be deleted. for example, a special arguments variable (or, as we know now, an activity object attribute) has DontDelete. the length attribute of the function instance also has the DontDelete attribute.
Copy codeThe Code is as follows:
(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 attribute corresponding to the function parameter also has the DontDelete feature since the creation, so we cannot delete it.
Copy codeThe Code is as follows:
(Function (foo, bar ){
Delete foo; // false
Foo; // 1
Delete bar; // false
Bar; // 'blah'
}) (1, 'blah ');
Undeclared values:
You may also remember that an unspecified value assignment will create an attribute on the global object, unless this attribute has been found elsewhere before the global object in the scope chain. now we know the difference between attribute assignment and variable declaration-the latter sets the DontDelete attribute, but the former does not. we must be clear why an undeclared value assignment creates a deletable attribute.
Copy codeThe Code is as follows:
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;
Delete foo; // false
Typeof foo; // "number"
Delete bar; // true
Typeof bar; // "undefined"
Note: The feature is determined when the attribute is created, and the assigned value does not modify the feature of the existing attribute. It is very important to understand the difference.
Copy codeThe Code is as follows:
/* '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"
Firebug confusions:
What happened in Firebug? Why can the variables declared on the console be deleted? Isn't that against what we have learned before? Well, as I said before, the Eval code has a special performance in the face of variable declarations. the variables declared in Eval are actually created as attributes without the DontDelete feature.
Copy codeThe Code is as follows:
Eval ('var foo = 1 ;');
Foo; // 1
Delete foo; // true
Typeof foo; // "undefined"
Similarly, when called in function code:
Copy codeThe Code is as follows:
(Function (){
Eval ('var foo = 1 ;');
Foo; // 1
Delete foo; // true
Typeof foo; // "undefined"
})();
This is the basis for abnormal Firebug behavior. all texts in the console are parsed and executed as Eval code, rather than global or function code. obviously, all variables declared here will eventually become attributes without the DontDelete feature, so they can be easily deleted. we need to know the difference between the global code and the Firebug console.
Use Eval to delete variables:
This interesting eval behavior, coupled with another aspect of ECMAScript, can technically allow us to delete the "non-deletable" attribute. one thing about function declaration is that they can overwrite variables with the same name in the same execution context.
Copy codeThe Code is as follows:
Function x (){}
Var x;
Typeof x; // "function"
Note how function declaration obtains priority and overwrites variables of the same name (or, in other words, the same attribute in the variable object. this is because the function declaration is instantiated after the variable Declaration and is allowed to overwrite them (variable Declaration ). function declaration not only replaces the value of an attribute, but also replaces the attribute. if we declare a function through eval, the function should replace the original (replaced) attribute features with its own features. in addition, because the variables declared through eval will create an attribute without the DontDelete feature, instantiating this new function will actually Delete the existing DontDelete feature from the attribute, so that an attribute can be deleted (and the value is clearly directed to the newly created function ).
Copy codeThe Code is as follows:
Var x = 1;
/* Can't delete, 'X' has DontDelete */
Delete x; // false
Typeof x; // "number"
Eval ('function x (){}');
/* 'X' property now references function, and shoshould have no DontDelete */
Typeof x; // "function"
Delete x; // shoshould be 'true'
Typeof x; // shocould be "undefined"
Unfortunately, this kind of "spoofing" does not work in any of the current implementations. Maybe I missed something here, or this kind of behavior is just so obscure that the implementers did not notice it.
Browser compatibility:
Theoretically, it is useful to understand how things work, but practice is the most important. Do browsers comply with standards when creating or deleting variables or attributes? The answer is: In most cases, yes.
I wrote a simple test set to test the browser's compatibility with the delete operator, including testing in global code, function code, and Eval code. the test set checks whether the return values and attribute values of the delete operator (as they should be) are actually deleted. the return value of delete is not as important as its actual results. if delete returns true rather than false, this is not important. It is important that the attributes with the DontDelete feature are not deleted, and vice versa.
Modern browsers are generally quite compatible. apart from the eval features I mentioned earlier, the following browsers have passed all the test sets: Opera 7.54 +, Firefox 1.0 +, Safari 3.1.2 +, and Chrome 4 +.
Safari 2.x and 3.0.4 have problems when deleting function parameters. These attributes do not seem to have been created without DontDelete, so they can be deleted. safari 2. x has more problems-deleting non-referenced variables (such as delete 1) throws an exception; function Declaration creates deletable attributes (however, it is strange that, variable declaration does not); the variable declaration in eval will become non-deletable (but the function declaration can be deleted ).
Like Safari, Konqueror (3.5, not 4.3) throws an exception (for example, delete 1) When deleting a non-reference type, and mistakenly changes the function variable to deletable.
Note:
I tested the latest versions of chrome, firefox, and IE, which are basically retained in the case that all the other passes will be fail. at the same time, UC and some mobile browsers are tested. Besides Nokia E72's built-in browsers, Fail and 16 are also tested. Most of the other built-in browsers have the same effect as desktop browsers. but it is worth mentioning that the browser of Blackberry Curve 8310/8900 can pass Test 23, which surprised me.
Gecko DontDelete bug:
Gecko 1.8.x browser -- Firefox 2.x, Camino 1.x, Seamonkey 1. x and so on. -- it shows a very interesting bug. Explicit attribute assignment will delete its DontDelete feature, even if this property is created through variable declaration or function declaration.
Copy codeThe Code is as follows:
Function foo (){}
Delete foo; // false (as expected)
Typeof foo; // "function" (as expected)
/* Now assign to a property explicitly */
This. foo = 1; // erroneously clears DontDelete attribute
Delete foo; // true
Typeof foo; // "undefined"
/* Note that this doesn't happen when assigning property implicitly */
Function bar (){}
Bar = 1;
Delete bar; // false
Typeof bar; // "number" (although assignment replaced property)
Surprisingly, Internet Explorer 5.5-8 has passed the complete test set. In addition to deleting non-reference types (such as delete 1), an exception is thrown (just like the old Safari ). however, there is a more serious bugs in IE, which is not so obvious. these buckets are related to Global objects.
IE bugs:
What is Internet Explorer's bugs in this chapter? Wow! It's amazing!
In IE (at least IE 6-8), the following expression throws an exception (when executed in Global Code ):
This. x = 1;
Delete x; // TypeError: Object doesn' t support this action
This one will also, but it will throw different exceptions, which makes things more interesting:
Var x = 1;
Delete this. x; // TypeError: Cannot delete 'this. X'
It seems that in IE, the variable declaration in the Global Code does not create attributes on the global object. create attributes by assigning values (this. x = 1) and then delete it through delete x. An error is thrown. create an attribute through declaration (var x = 1) and then delete this. x to delete it will throw another error.
But this is not all. an explicit value assignment is used to create an attribute. In fact, an exception is thrown during deletion. there are more than errors here, And the created attributes seem to have the DontDelete feature, which of course should not.
This. x = 1;
Delete this. x; // TypeError: Object doesn't support this action
Typeof x; // "number" (still exists, wasn' t deleted as it shoshould have been !)
Delete x; // TypeError: Object doesn' t support this action
Typeof x; // "number" (wasn't deleted again)
Now, we will think that in IE, undeclared values (attributes should be created on Global Objects) will indeed create deletable attributes.
X = 1;
Delete x; // true
Typeof x; // "undefined"
However, if you delete this attribute by using the this reference in the global code (delete this. x), a similar error will pop up.
X = 1;
Delete this. x; // TypeError: Cannot delete 'this. X'
If we want to summarize this behavior, it seems that we use delete this from the global code. it is never possible to delete the variable. when the attribute in the question is explicitly assigned (this. when creating an object, delete throws an error. When an attribute is created by an undeclared value (x = 1) or declaration (var x = 1, delete throws another error.
Delete x, on the other hand, should only throw an error when the attribute is created by explicitly assigning values -- this. x = 1. if an attribute is created through declaration (var x = 1), The delete operation will never happen, And the delete operation will return false correctly. if an attribute is created using an undeclared value assignment (x = 1), The delete operation will work as expected.
I thought about this issue again this September. Garret Smith suggested that in IE,
"The global variable object is implemented as a JScript object, and The global object is implemented by The host ".
Garret uses Eric Lippert's blog entry as a reference.
We can more or less confirm this theory by implementing some tests. note that this and window seem to point to the same object (if we can trust the = Operator), but the variable object (the object where the function declaration is located) it is different from what this points.
Copy codeThe Code is as follows:
/* In Global code */
Function getBase () {return this ;}
GetBase () === this. getBase (); // false
This. getBase () === this. getBase (); // true
Window. getBase () === this. getBase (); // true
Window. getBase () === getBase (); // false
Misunderstanding:
Understanding why things work in that way can't be underestimated. I have seen some misunderstandings about the delete operator on the Internet. for example, the answer on Stackoverflow (with surprising rating) confidently explains
"When the target operand is not an object attribute, delete should be non-operational ".
Now that we have understood the core of the delete operation, the error in this answer becomes obvious. delete does not distinguish between variables and attributes (in fact, they are all reference types for delete). In fact, it only cares about the DontDelete feature (and whether the attribute exists ).
It is also very interesting to see various misunderstandings and refute each other. In the same topic, one person first suggested to delete only the variable (this will not work unless it is declared in eval ), the other person provides an error correction, indicating how delete is used to delete variables in global code, but not in function code.
Be extremely careful when interpreting JavaScript on the Internet. The ideal method is to always understand the nature of the problem .;)
Delete and Host Object ):
The delete algorithm is like this:
Returns true if the operand is not of the reference type.
If the object does not have a direct attribute of this name, true is returned (as we know, the object can be an active object or a global object)
If the attribute exists but has the DontDelete feature, false is returned.
In other cases, delete the attribute and return true.
However, the behavior of the delete operator on the host object is unpredictable. in fact, there is nothing wrong with this behavior: (according to the standard), the host object is allowed for methods like read (internal [[Get]), write (internal [Put) and delete (internal [[Delete] method). Several operators implement any behavior. the reason for this restriction on custom [[Delete] behaviors is that the Host object is so messy.
We have seen some Internet Explorer geeks. Deleting a specific object (apparently implemented as a host object) will throw an error. some Firefox versions are deleting windows. location will throw. when the operand is a host object, you cannot trust the return value of delete. let's see what happened in Firefox:
Copy codeThe Code is as follows:
/* "Alert" is a direct property of 'window' (if we were to believe 'hasownproperties ')*/
Window. hasOwnProperty ('alert '); // true
Delete window. alert; // true
Typeof window. alert; // "function"
Delete window. alert returns true, even if this attribute has no reason for such a result. it will be resolved to a reference (so it will not return true in the first step ). this is a direct property of the window object (so true is not returned in step 2 ). therefore, the only condition that delete can return true is that it reaches step 4 and actually deletes the attribute. however, this property has never been deleted.
The implication of this story is: Never trust the Host object.
ES5 strict mode:
So what does the strict-mode ECMAScript5 bring to us? It introduces few restrictions. when the expression of the delete operator is a direct reference to a variable, a function parameter or function identifier, a syntax error will be thrown. in addition, if the attribute has an internal feature [[retriable] = false, a type error will be thrown.
Copy codeThe Code is as follows:
(Function (foo ){
"Use strict"; // enable strict mode within this function
Var bar;
Function baz (){}
Delete foo; // SyntaxError (when deleting argument)
Delete bar; // SyntaxError (when deleting variable)
Delete baz; // SyntaxError (when deleting variable created with function declaration)
/* 'Length' of function instances has {[[retriable]: false }*/
Delete (function () {}). length; // TypeError
})();
In addition, deleting undeclared variables (or unresolved references) will also throw a syntax error:
"Use strict ";
Delete I _dont_exist; // SyntaxError
An undeclared value assignment is similar to a behavior of an undeclared variable in a strict mode (except that a reference error is triggered this time rather than a syntax error ):
"Use strict ";
I _dont_exist = 1; // ReferenceError
As you understand now, all restrictions are more or less justified, because deleting variables, function declarations, and parameters can cause so much confusion. instead of silently ignoring the delete operation, the strict mode adopts a more radical and descriptive measure.
Summary:
This blog post became quite long at the end, so I am not going to talk about anything like deleting an array object with delete or what it means. you can refer to the MDC article for specific explanations (or read the standards and do your own experiments ).
Here is a brief summary of how the delete operation in JavaScript works:
Variables and function declarations are attributes of activity objects or global objects.
The attribute has some features. The DontDelete feature determines whether the attribute can be deleted.
Variables and function declarations in global or function code always create attributes with the DontDelete feature.
Function parameters are always the attributes of the active object and contain DontDelete.
Variables and functions declared in Eval code always create attributes without DontDelete.
The new attribute has no features when it is created (of course there is no DontDelete ).
The Host object is allowed to decide how to respond to the delete operation.
If you want to be more familiar with what is described here, see ECMA-262 3rd edition specification.
I hope you can enjoy this article and learn something new. You are welcome to raise any questions, suggestions, or correct them.