70

I can't find any information on this issue; why doesn't the following code work in IE?

window.x = 45;
delete window.x;
// or delete window['x'];

IE reports an "object doesn't support this action" error. Does it have anything to do with that iterating over window properties in IE issue?

Sam
  • 7,252
  • 16
  • 46
  • 65
gasper_k
  • 1,098
  • 1
  • 7
  • 11
  • 30
    And just to be clear, because it doesn't look like anyone's actually said this in any of the answers: This is a *bug* in Internet Explorer. There is nothing in the 1999 (3rd edition) specification that allows for throwing an exception from `delete`, even if the property is non-existant or undeleteable (which your `window.x` should not be in any case), and the new 5th edition spec only allows exceptions thrown from `delete` in the new strict mode. There's nothing special about `window` in this regard. And yet, the JScript engine in IE8 *still* exhibits this bug, in 2010. *sigh* – T.J. Crowder Mar 28 '10 at 12:44
  • 3
    [Good relevant article](http://perfectionkills.com/understanding-delete/). – alex Nov 18 '11 at 05:31
  • T.J. Crowder, window is not an object, it's an accessor to the root namespace. It doesn't have properties as such, so when you run delete on it, such as in this case, it's not obliged to actually remove them for any reason. Setting undefined on the object's name is fine to do because the gc will come through and eliminate unreferenced objects. Hope this helps understand the actual issue here and why this isn't so much a bug as it is a poor implementation choice for the language which is slowly updating to modernize – Jeffrey Gilbert Oct 27 '15 at 20:12

4 Answers4

49

Gasper made a comment with the solution he finished on, but I think it's worth calling out as an actual answer:

try { 
    delete window.x; 
} catch(e) { 
    window["x"] = undefined; 
}

Interesting issue, I was just banging my head against it tonight. The exception is thrown on IE but not Firefox. I would suspect this workaround leaks memory, so use it sparingly.

It was asked, why not just assign undefined? It matters if you want to enumerate the keys later (though if you're relying on the workaround, the key enumeration still won't do what you want...). But anyhow, to highlight the difference between delete and simply assigning undefined (http://jsfiddle.net/fschwiet/T4akL/):

var deleted = {
    a: 1
};

var cleared = {
    a: 1
};

delete deleted["a"];
cleared["a"] = undefined;

for(var key in deleted) {
    console.log("deleted has key", key);
}

for(var key in cleared) {
    console.log("cleared has key", key);
}

console.log("deleted has a?", deleted.hasOwnProperty('a'));
console.log("cleared has a?", cleared.hasOwnProperty('a'));

Produces output:

cleared has key a
deleted has a? false
cleared has a? true 
Arnav Thorat
  • 3,078
  • 3
  • 8
  • 33
Frank Schwieterman
  • 24,142
  • 15
  • 92
  • 130
38

I would do it this way:

    window[x] = undefined;
    try{
        delete window[x];
    }catch(e){}
user155314
  • 404
  • 3
  • 3
  • thanks, that's what I did in the end. It throws an exception in IE, but it's caught and no damage is done. – gasper_k Aug 13 '09 at 11:26
  • 1
    The most in-depth explanation of delete I've seen is here, this is the IE section. (In case someone comes to this with a more complicated issue in the future) http://perfectionkills.com/understanding-delete/#ie_bugs – Patrick McGuire Nov 18 '16 at 16:18
2

Does this help?

window.x = 45;
alert(window.x);
window.x = null;

I tried this in IE and window.x did have a value, which proves it can be set. Setting the value to null is your best bet for clearing it out.

Fenton
  • 241,084
  • 71
  • 387
  • 401
  • Unfortunately this doesn't remove the variable from memory, it just gives it a null value, but this is the only option as far as I can tell. – Andy E Jul 02 '09 at 11:50
  • 1
    Thanks. I've gone a step further and used window.x = undefined. This still isn't what I want, but it'll do. It's strange that I haven't found any useful information on the web about this. – gasper_k Jul 02 '09 at 17:28
1

I implemented this solution when dealing with caching my own data - the data wasn't much the the frequency of the cache was such that the memory leak might have become an issue. It's costly, but periodically remapping the object was the easiest way for me to be sure it wasn't getting out of hand.

obj = {a: 1, b: 2, c: 3};
var max;

function unset(obj, key) {
    try {
        delete obj[key];
    } catch (e) {
        obj[key] = undefined;
    }

    max++;

    if(max > 200) {
        var keys = Object.keys(obj);
        var len = keys.length;
        var n_obj = {};
        for(var i = 0; i < len; i++) {
            if(obj.hasOwnProperty(keys[i]) && obj[keys[i]] !== undefined) {
                n_obj[keys[i]] = obj[keys[i]];
            }
        }
        return n_obj;
    }
    return obj;
}

obj; //{a: 1, b: 2, c: 3}
obj = unset(obj, "b"); //{a: 1, b: undefined, c: 3} OR {a: 1, c: 3}
//and then eventually we'll garbage collect and...
obj = unset(obj, "b"); //{a: 1, c: 3}   

Hopefully, that's useful to some!

Mikebert4
  • 156
  • 4
  • 2
    `Object.keys()` won't work in <= IE8 (which are the ones causing trouble with `delete` in the first place). Also, you probably meant `obj[key] = undefined` inside the catch block. ;] – WynandB Nov 07 '14 at 05:41
  • that would be it! revised. – Mikebert4 Feb 06 '15 at 00:44