Search code examples
javascriptgoogle-analyticsclosuresgoogle-closure-compiler

Advanced Closure Compatibility and static types - Usage of types like undefined and global functions like localStorage.getItem();


I'm just wondering whats the correct way to check if a function is undefined with a script which will be closured in advanced mode and how to access global functions?

E.g. an example of checking if google analytics is loaded:

typeof window["ga"] == "function"
typeof window["ga"] !== "undefined"

But is the following bullet proof with closure compilers as well?

typeof window["ga"] == function
typeof window["ga"] !== undefined

And what about localStorage. Like magic the following works in chrome:

if (localStorage != undefined ) myvariabel = localStorage.getItem('myvariable')

But in seems to me like dirty coding. In my mind the following would be correct or?

if(typeof localStorage != "undefined")
// or even better the following since per definition local storage is an attribute of window:
if(typeof window["localStorage"] != "undefined") myvariabel = window["localStorage"].getItem('myvariable')

In this context is .getItem safe to use in advanced compiler mode or do I have to code:

if(typeof window["localStorage"] != "undefined") myvariabel = window["localStorage"]["getItem"]('myvariable')

Solution

  • The typeof operator will give you a string describing the type.

    function is not a string, and expects to be followed by certain characters. typeof window["ga"] == function will therefore throw an exception.

    typeof will always give you a string. A string is never an undefined value. typeof window["ga"] !== undefined will always give you a true result.

    So no. Not using strings isn't bullet proof. Quite the opposite; it won't work anywhere.


    And what about localStorage

    This is no different to any other variable.

    Like magic the following works in chrome

    if (localStorage != undefined )

    Now you are testing if the variable is equal to undefined, not if using typeof is. That's a completely different problem.

    That will work… but only if:

    • undefined hasn't been masked by a different variable that is defined and
    • localStorage has been declared

    If it hasn't been declared that you will get a ReferenceError and your script will abort (unless you are using try/catch).

    So no. Never compare a variable directly to undefined.

    There is a slim possibility that undefined isn't what you think it is. Most of the time you care about the variable being declared as well as being defined. And the rest of the time you can continue to use typeof because it works reliably everywhere and using it as a matter of habit is better then mixing and matching and sometimes getting it wrong.