This code:
var a = {},
b = {key:'b'},
c = {key:'c'};
a[b] = 111;
a[c] = 222;
console.log(a[b]);
Outputs: "222" (not "111").
Explanation:
b
andc
will both be converted to "[object Object]"
Can someone explain why this is?
javascript
This code:
var a = {},
b = {key:'b'},
c = {key:'c'};
a[b] = 111;
a[c] = 222;
console.log(a[b]);
Outputs: "222" (not "111").
Explanation:
b
andc
will both be converted to "[object Object]"
Can someone explain why this is?
JavaScript's built-in objects do provide hashtable functionality using the square brackets notation for properties, provided your keys are strings or numbers
That seems to be incorrect - object keys may be strings or (since ECMAScript 2015, aka ECMA-262 ed 6) symbols. But that is a different topic to square bracket property access.
See ECMA-262 ed 3 ยง 11.2.1 (Please also see ECMAScript 2017 (draft).):
Properties are accessed by name, using either the dot notation:
MemberExpression . IdentifierName
CallExpression . IdentifierName
or the bracket notation:
MemberExpression [ Expression ]
CallExpression [ Expression ]
The dot notation is explained by the following syntactic conversion:
MemberExpression . IdentifierName
is identical in its behaviour to
MemberExpression [ <identifier-name-string> ]
and similarly
CallExpression . IdentifierName
is identical in its behaviour to
CallExpression [ <identifier-name-string> ]
where <identifier-name-string> is a string literal containing the same sequence of characters after processing of Unicode escape sequences as the IdentifierName.
So when using dot notation, the bit after the dot must fit the criteria for an IdentifierName. But when using square brackets, an expression is provided that is evaluated and resolved to a string.
Briefly, square bracket notation is provided so that properties can be accessed using an expression, e.g.
var y = {};
var x = 'foo';
y[x] = 'foo value';
In the above, x
is provided in square brackets so it is evaluated, returning the string 'foo'. Since this property doesn't exist on y
yet, it is added. The foo
property of y
is then assigned a value of 'foo value'.
In general terms, the expression in the square brackets is evaluated and its toString()
method called. It is that value that is used as the property name.
In the dot property access method, the identifier is not evaluated, so:
y.bar = 'bar value';
creates a property bar
with a value bar value
.
If you want to create a numeric property, then:
y[5] = 5;
will evaluate 5
, see it's not a string, call (more or less) Number(5).toString()
which returns the string 5
, which is used for the property name. It is then assigned the value 5
, which is a number.
This answer was written when ECMAScript ed3 was current, however things have moved on. Please see later references and MDN.
The problem here has to do with how an Object
's keys are set. From MDN:
Parameters
nameValuePair1, nameValuePair2, ... nameValuePairN
- Pairs of names (strings) and values (any value) where the name is separated from the value by a colon.
value
- Any value.
An object's values can be accessed (via the appropriate key) in three ways:
var o = {};
var key = "fun";
// method 1:
o[key] = "the key will be equal to `key.toString()"
// method 2:
o.key = "the key will be equal to 'key'"
// method 3:
o["key2"] = "the key will be equal to `key2`"
/*
{
"fun" : "the key will be...", // method 1
"key" : "the key will be...", // method 2
"key2": "the key will be..." // method 3
}
*/
When using bracket notation, you need to mind the gap...between the brackets! Objects set their keys and values using the toString
method, unless they're passed a string (then there's no point in toString
). When using the dot notation, they use .key
as the key.
Let's look at your case:
var a = {}
, b = {}
, c = {}
;
c[a] = a;
// `a` is not a string, and we're using brackets, so the key
// will be equal to `key.toString()`:
// a.toString() === "[object Object]"
// Try the following in your console: `{}.toString()`
// Note how this is different from console.log({}), since
// the console exposes your object (that's why the dev console is useful)
// c is now: `{ "[object Object]" : a }`
c[b] = b;
// b is also an object, so `b.toString()` is the same as `a.toString()`
// that means c is now `{ "[object Object]" : b }`
assert c[a] === a
// a.toString() == b.toString() == "[object Object]"
// and we just noted that c was `{ "[object Object]" : b }`
// so of course this is false
assert c[b] === b
// true because c[b] == b;
assert c["[object Object]"] === b;
// also true
assert c.b === b
// false, since `c` has no "b" key (c.b is `undefined`)
Best Answer
[object Object]
is just the string representation of an object -- that is, the result of callingb.toString()
orc.toString()
.Object keys are always strings, so when you say:
JS will find the string representation of
b
([object Object]
), and use that. Same withc
.