Hacker News new | ask | show | jobs
by FrontAid 1365 days ago
Another similar gotcha is that the global-scoped `name` variable must be a string. See https://developer.mozilla.org/en-US/docs/Web/API/Window/name for details.

    var name = true;
    typeof name; // "string", not "boolean"
Luckily, this is not true within ES modules which you probably use most of the time anymway.
3 comments

That's not magic, it's just how property getter and setters work on the global:

    <script>
        var _value = "test value";
        Object.defineProperty(window, "testName", {
            get: () => _value,
            set: (value) => { _value = String(value) },
        });
    </script>
    <script>
        var testName = {};
        // prints [object Object] string
        console.log(testName, typeof testName);
        var name = {};
        // prints [object Object] string
        console.log(name, typeof name);
    </script>
the `var` doesn't create a new property since the getter and setter already exist.

Other properties have the same behavior, for example `status`.

Note: there's also LegacyUnforgeable which has similar behavior: https://webidl.spec.whatwg.org/#LegacyUnforgeable

Even if you're not using modules, using an IIFE avoids all this by making your variables local instead of having them define/update properties on the global.

It takes a special kind of human to name variable "name" but not have it be a string.
Something like

  name = {first: "Jane", last: "Doe"}
isn't obviously unreasonable. Which actually sets name to the string "[object Object]".
Falsehoods programming languages believe about names.
I work with such humans! I was looking at that exact situation a few moments ago.
I can imagine someone doing this if they were using "name" as a verb
I've been doing JS for like fifteen years, this one I never knew. Wow.

I must have never used "name" as a name for a global variable or just for ones that were strings.