'Using the variable "name" doesn't work with a JS object

The behaviour can be seen in this little snippet (execute it as a global script):

var name = {};
name.FirstName = 'Tom';
alert(name.FirstName);

The alert yields undefined in Chrome but works in IE and Firefox. I also get a weird value when I do

alert(name);


Solution 1:[1]

window.name has a special purpose, and is supposed to be a string. Chrome seems to explicitly cast it to a string, so var name = {}; actually ends up giving the global variable name (i.e. window.name) a value of "[object Object]". Since it's a primitive, properties (name.FirstName) won't "stick."

To get around this issue, don't use name as a global variable.

Solution 2:[2]

Your name variable is actually window.name, because top-level variables declared with var are attached to the global object.

The HTML5 spec requires that window.name is a DOMString. This means that the value of window.name can only be a sequence of characters, not an object.

In Chrome, an attempt to use window.name to store anything except a primitive string will coerce the value to a primitive string. For example:

window.name = {};
window.name === "[object Object]"; // true

You can avoid this problem by using a name variable that is not in the top-level scope:

(function() {
    var name = {};
    // this `name` is not `window.name`
    // because we're not in the top-level scope

    console.log(name);
})();

Solution 3:[3]

With ES6+, you could write your code as let name or const name. This won't assign it or try to override window.name. More on that here.

let name = {};
name.FirstName = 'Tom';
alert(name.FirstName);

Solution 4:[4]

window.name is used to set the name of the window, and since the window name can only be a string, anything you set to window.name is converted to a string. And strings, as primitive values, cannot have properties. The solution is to use a different variable name or a different scope.

Alternatively, you can use window.name as you like if you have this code first. I don't recommend this at all, but, just as a proof of concept:

(function () {
    var _name;
    window.__defineGetter__('name', function () {
        return _name;
    });
    window.__defineSetter__('name', function (v) {
        _name = v;
    });
})();

Additionally, you should use {} in place of new Object. Besides being more concise, it is also more efficient and more explicit.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Bergi
Solution 2 Ry-
Solution 3
Solution 4