Paul
Paul

Reputation: 141937

Why does undefined behave different than other variables?

I'm using Google Chrome 16.0.912.63 and have the following code:

__defineGetter__('x', function(){ 
    console.log('In Getter: x'); return 1; 
});

__defineGetter__('undefined', function(){ 
    console.log('In Getter: undefined'); return 2; 
});

console.log(x);
console.log(undefined);

The getter function for x is entered correctly, but the getter for undefined is never entered. The output logged to my console is:

In Getter: x
1
undefined

I was always under the impression that undefined behaves the same as any other global variable. I know that statements such as

undefined = 10;
undefined = null;
undefined = 'defined';

Are all valid, so what is different about undefined that makes it unable to have a getter (at least in my browser).

JSFiddle

Upvotes: 4

Views: 226

Answers (2)

pimvdb
pimvdb

Reputation: 154968

It seems __defineGetter__ just silently fails. Object.defineProperty throws an error:

redefine_disallowed

when you call this on Chrome:

Object.defineProperty(window, "undefined", {
    get: function() {
        return 2;
    }
});

On the other hand:

window.__defineGetter__("undefined", function() {
    return 2;
});

window.__lookupGetter__("undefined"); // undefined, so __defineGetter__ just ignored call

Why it works in Chrome's console:

When you define and get undefined in one go when pasting the code in the console, it works, because there are some functions behind the scenes being executed which use a with block referring to console._commandLineAPI:

if (injectCommandLineAPI && inspectedWindow.console) {
    inspectedWindow.console._commandLineAPI = new CommandLineAPI(
        this._commandLineAPIImpl,
        isEvalOnCallFrame ? object : null
    );
    expression = "with ((window && window.console && window.console._commandLineAPI) || {}) {\n" + expression + "\n}";
}
return evalFunction.call(object, expression);

So you're just defining console._commandLineAPI.undefined.

Another point is that it overwrites console._commandLineAPI (see above code), so it does not work if you define and get undefined as two commands, since the getter has been thrown away by the overwriting by the time you try to get undefined.

This, plus the fact that it does not overwrite window.undefined, is most probably why it works in the console.

Upvotes: 2

Ry-
Ry-

Reputation: 225281

It doesn't behave like any normal variable, it just pretends to, at least on Firefox and Chrome. Try it:

var x;
undefined = "Hello!";
x === undefined; // true; undefined doesn't change

It's more like a readonly property but doesn't throw an error when it's written to.

Upvotes: 3

Related Questions