3

I was planning on using the delete operator in JavaScript for something, when I decided to remind myself how it worked by playing with it some. I understand that "delete" is supposed to be used on object properties, but I wanted to see how it behaves on variables. However, some weird results occurred when I put the following snippet of code in different browsers:

var one = 1;
delete one;
console.log(one); // prints out 1 in Chrome, but not in Safari or Firefox

In Safari, the JavaScript console printed out the error "ReferenceError: Can't find variable: one". Firefox gave a similar response: "ReferenceError: one is not defined". However, Chrome printed out the value of the variable, 1. Can anyone explain why Chrome behaves differently than Safari and Firefox in this regard?

4
  • Because that is not how delete is supposed to be used. one should remain there with the value 1 since delete one shouldn't do anything. Quoting from MDN: delete is only effective on an object's properties. It has no effect on variable or function names. Commented Jun 24, 2014 at 23:19
  • why are you trying to delete a variable? What are you trying to accomplish? Commented Jun 24, 2014 at 23:20
  • The delete operator is only useful to delete properties of an object, like this: delete someObject.foo or delete someObject[propName] Commented Jun 24, 2014 at 23:20
  • MDN delete Commented Jun 24, 2014 at 23:21

4 Answers 4

3

Don't trust the console. Some codes behave different there.

The following will alert 1 if you run it on a real page:

var one = 1;
delete one;
alert(one);

Demo

(Tested on Firefox, Chrome, IE, Safari and Opera.)


Understanding delete explains why the console (or firebug) shows a different behavior:

Every execution context has a so-called Variable Object associated with it. Similarly to execution context, Variable object is an abstract entity, a mechanism to describe variable instantiation. Now, the interesing part is that variables and functions declared in a source text are actually added as properties of this Variable object.

Finally, variables declared within Eval code are created as properties of calling context’s Variable object.

When declared variables and functions become properties of a Variable object — either Activation object (for Function code), or Global object (for Global code), these properties are created with DontDelete attribute. However, any explicit (or implicit) property assignment creates property without DontDelete attribute. And this is essentialy why we can delete some properties, but not others.

So what happens in Firebug? Why is it that variables declared in console can be deleted, contrary to what we have just learned? Well, as I said before, Eval code has a special behavior when it comes to variable declaration. Variables declared within Eval code are actually created as properties without DontDelete.

Sign up to request clarification or add additional context in comments.

4 Comments

Hmm, the alert is behaving the same way as the console for me.
@Ylluminarious console.log and alert should have same behavior (I changed it to make it more visible). The difference is running the code in the console or in a real page.
Ah, ok, I see what you're saying.
I like the article you posted so i'll give you the +1 for that... but I don't feel you've really explained why its the answer as it applies to the question. I will revise mine also.
2

Let's checkout the docs on delete from MDN.

The delete operator removes a property from an object.

You are using it a way that doesn't make much sense, that is to remove a local variable.

Those docs also say:

Throws in strict mode if the property is an own non-configurable property (returns false in non-strict). Returns true in all other cases.

Which means your usage here would throw an exception in strict mode, since you are using delete in an unsupported way. This is proven when you do:

var one = 1;
delete one; // returns false

And as the docs mention, a return value of false means the delete operation did not succeed.


If you use it properly, it should behave like you expect:

var obj = {one: 1};
delete obj.one;    // returns true
alert(obj.one);    // alerts "undefined"

5 Comments

Yeah, I understand that you're supposed to use delete on object properties; I was more or less playing with it to see how it works with variables.
Why they behave differently is hard to say. likely implementation details, console behavior discrepancies, or not completely adhering to the stndards. But does it really matter? If different browsers fail differently when you do it wrong, then don't do it wrong :)
True, I might not do what I was planning on doing because it acts weirdly when I use it improperly.
If your plan starts with "I want to use the the delete operator improperly" then perhaps you need a new plan.
In a browser, delete one; is perfectly legal code because one doesn't exist, which is perfectly legal. delete one = true. It's well and "proper".
-1

I think the answer he's looking for, and someone essentially said earlier, but muddied up the clarity by adding more explanation through an edit should be restated thus:

When you use a method in a way that was not original dictated in the standard, then the result is undefined and therefore varies from browser to browser (because each essentially has a different js engine) in the way that it's handled.

1 Comment

I do not believe that this is an issue of respecting the standard, it is an issue as to how the console views its code in respect to the DOM. There is no standard for the DOM's root inheritance "behavior" in browser consoles. Thus some consoles do not see window as parent by default.
-1

Revised Answer:

Based on feedback from @Oriol concerning property attributes. I have found that the real issue here is concerning Property Attributes (See ECMA-262 edition 5.1 section 8.6.1) and the Variable Environment's execution context (See ECMA-262 edition 5.1 section 10.3)

Can anyone explain why Chrome behaves differently than Safari and Firefox in this regard?

var one = 1;
delete one;
console.log(one); // Returns 1.. but why?

Two things are happening here:

  1. The var declaration binds the declared object into an "Execution context" that is distinctly different from the Global (window) one.
  2. JavaScript evaluates the [[Configurable]] property to determine if its "OK" to delete

Concerning #1

The var declaration in the code establishes a VariableEnvironment whereby the value is bound to the object in a distinctly different execution context (scope) than the global one. So naturally, when var is not used the VariableEnvironment is interpreted in a global execution binding process, making statements like one = 1; or delete one; possible.

var one = 1; // Execution context #1 has a unique VariableEnvironment
delete one; // Execution context #2 has a global VariableEnvironment
console.log(one); // Return the value from 'var one'

This complies with the language spec:

10.4 Establishing an Execution Context

Evaluation of global code or code using the eval function (15.1.2.1) establishes and enters a new execution context...

10.4.2 Entering Eval Code

The following steps are performed when control enters the execution context for eval code:

If there is no calling context or if the eval code is not being evaluated by a direct call (15.1.2.1.1) to the eval function then, Initialise the execution context as if it was a global execution context using the eval code...

Concerning #2

Chrome and JSFiddle are both doing the right thing here. The the reason has to do with the [[Configurable]] property attribute, which is assigned to both native and user-created properties behind the scenes. When a user-created property is established, this attribute is set to true. This allows the developer to execute assign and delete commands on the property.

var test = {};
test.me = "OK" // [[Configurable]] is true so No Problem!
delete test.me // Good here too!

To prevent certain situations where object properties should not ever be deleted or modified [[Configurable]] is set to false by default. Which respects the language spec:

If the value of an attribute is not explicitly specified by this specification for a named property, the default value defined in Table 7 is used...

[[Configurable]] false

var test2 = [1,2,3];
console.log(test2.length); // length property is '3'
console.log(delete test2.length); // NOPE [[Configurable]] is false

Same is true in function arguments in a function scope:

(function foo(one) {
 console.log(delete one);
})(); // NOPE (false)

What can we draw from both findings?

From this we can understand that Firefox and Safari do not does not play by the rules. When var one=1; is declared in either of these browser's consoles, properties in this scope are incorrectly deemed [[Configurable]] by default and thus deletes var one and not the implied window.one.

In Firefox/Safari:

var one = 1; // var 'one'?
delete one; // NUKE var 'one'!
console.log(one); // ReferenceError: 'one' is not defined :'(

"OK Wait! So why then is delete one true by itself?

It plays out as determined by the language spec (10.4.2):

var one = 1; // VariableEnvironment not global or [[Configurable]]
delete one; // FALSE

...

delete one; // TRUE VariableEnvironment global and [[Configurable]]

...

var one = 1; // VariableEnvironment not global or [[Configurable]]
delete this.one; // TRUE VariableEnvironment is global and [[Configurable]]

2 Comments

"I personally believe jsfiddle in this case is actually wrong": no, the behavior shown in jsfiddle follows the spec, so it's the good one. "My guess is that jsfiddle does not attach variables to the parent window by default": of course, because the code runs in an onload event listener, not in global context - you can change it in jsfiddle options, but delete won't work anyway because of var. "Just to make things even stranger one = 1; alert(window.one)": this is unrelated with delete, and is a bad practice only allowed in non strict mode.
@Oriol You can change the executing code's load state to any of the available options in jsfiddle. They all do the same thing. - The last example I showed was to illustrate that one was swallowed by window. Which it was. No one claimed it to be good code (or any of this for that matter).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.