题目:下面代码输出的结果是什么?
var a={}, b='123', c=123;
a[b]='b';
a[c]='c';
console.log(a[b]); // c
// example 2
var a={}, b=Symbol('123'), c=Symbol('123');
a[b]='b';
a[c]='c';
console.log(a[b]);// b
// example 3
var a={}, b={key:'123'}, c={key:'456'};
a[b]='b';
a[c]='c';
console.log(a[b]);// c
本题考查的是对象的键名转换:
- 对象的键名只能是字符串类型与Symbol类型
- 其他类型的键名会被转为相应的字符串形式
- 键名为对象形式的会调用toString()方法,最终为[object Object]
example 1
var a={}, b='123', c=123;
a[b]='b';
console.log( a);// {123: "b"}
a[c]='c';
console.log(a);// {123: "c"}
console.log(a[b]);// c
- 首先对象a的键名b为字符串"123",符合规定,此时打印a为{123: “b”}
- 对象a的键名c为数字类型,要转为字符串类型"123",此时将覆盖上面的键名"123"。对象a为{123: “c”}
- 最终打印c
example 2
var a={}, b=Symbol('123'), c=Symbol('123');
a[b]='b';
a[c]='c';
console.log(a[b]);// b
- 对象a的键名b,c都是Symbol类型,满足条件,并且Symbol类型值是唯一的,互不影响。所以最终结果打印b
example 3
var a={}, b={key:'123'}, c={key:'456'};
a[b]='b';
console.log(a); // {[object Object]: "b"}
a[c]='c';
console.log(a); // {[object Object]: "c"}
console.log(a[b]);// c
- 对象a的键名b、c都是对象,根据上面的规则,键名为对象形式的会调用toString()方法,最终为[object Object]
- 当执行 a[c]='c’时,会覆盖a[b] = ‘b’,最终打印结果为c。
要想不被覆盖,怎么做?
这里会想到es6新增的Map方法,它可以使对象的键名为任意类型。
example 1:
var a= new Map(), b='123', c=123;
a.set(b, "b");
a.set(c, "c");
console.log(a)// Map(2) {"123" => "b", 123 => "c"}
console.log(a.get(b)); // b
example 2:
var a=new Map(), b={key:'123'}, c={key:'456'};
a.set(b, "b");
a.set(c, "c");
console.log(a)// Map(2) {{…} => "b", {…} => "c"}
console.log(a.get(b)); // b