Search code examples
javascriptcastingcomparison-operators

Comparing against an undefined property is not an error in JavaScript


In JavaScript, comparisons that involve undefined properties are evaluated as false, rather than throwing an error, even in "strict" mode. This has created more than one hard-to-resolve bug in my code.

Is there any way to a) detect these mistakes, or b) mitigate against them?

> let x = {foo: 1}
> x.foo == 2 // Sensible behaviour
false
> x.floo // Where floo is a typo.
ReferenceError: floo is not defined
> x.floo == 2 // Nonsensical behaviour
false

Solution

  • Although @jonrsharpe is absolutely right that you should use Typescript if you need that level of control, just for fun, here's a pure javascript implementation. Wrap your object in strict(...) and you will get reference errors on undefined props:

    const SPECIAL_PROPS = [
        // well-known symbols
        ...Object.getOwnPropertyNames(Symbol).map(p => Symbol[p]),
        // used by JSON.strinfigy
        'toJSON',
        // something else?
    ];
    
    let strict = obj => new Proxy(obj, {
        get(t, p) {
            if (p in t)
                return t[p];
            if (!SPECIAL_PROPS.includes(p))
                throw new ReferenceError(`property ${String(p)} is not defined`);
        }
    });
    
    let x = strict({foo: 1})
    x.foo == 2 // Sensible behaviour
    x.floo == 2 // Reference error

    Needless to say, this is a purely runtime check, which kinda defeats the whole purpose.