为什么两个不同的键在一个对象中互相覆盖?

时间:2019-01-04 21:25:43

标签: javascript

我分配了以下三个变量:

const a = {key:true}
const b = {key:false}
const c = {[a]:'1',[b]:'2'}

当我尝试将以下内容登录到控制台时:

console.log(c[a],c[b])

我得到了以下内容:

2 2

我以为我应该得到:

1 2

我为什么错了,我该如何解决?

4 个答案:

答案 0 :(得分:9)

对象只能将字符串(或符号)作为其键。如果您尝试使用非字符串,它将被转换为字符串。因此,当您将c[a]设置为1时,a是一个对象,这意味着它需要转换为字符串。因此,您最终将c["[object Object]"]设置为1。然后,当您设置c[b]时,您会做同样的事情,再次转换为"[object Object]",从而覆盖已经存在的值。

尝试注销c来查看此内容:

const a = {key:true}
const b = {key:false}
const c = {[a]:'1',[b]:'2'}
console.log(c);

需要使用对象作为键是不寻常的,但是如果需要,可以使用Maps代替对象

const a = {key:true}
const b = {key:false}
const c = new Map();
c.set(a, '1');
c.set(b, '2');
console.log(c.get(a));
console.log(c.get(b));

答案 1 :(得分:4)

  

我为什么错了,我该如何解决?

对象属性名称将转换为字符串(如果它们不是字符串或符号)。默认情况下,对象值序列化为[object Object],因此对于JavaScript,两个值都相同:

const a = {key:true}
const b = {key:false}

console.log('a', a.toString());
console.log('b', b.toString());


1。。您可以实现自己的toString方法来将对象序列化为独特的字符串:

function toString() {
  return this.key.toString();
}

const a = {key:true, toString}
const b = {key:false, toString}
const c = {[a]:'1',[b]:'2'}
console.log(c[a],c[b]) 

但这不会让您恢复用作键的原始值(您可以可以使用对象的JSON表示作为键,您可以将其转换回对象,但是仅在“关键对象”仅包含可以用JSON表示的值的情况下有效。


2。。您可以使用Map代替对象,该对象允许将任意值用作键:

const a = {key:true}
const b = {key:false}
const c = new Map([[a, '1'], [b, '2']]);
console.log(c.get(a),c.get(b)) 

请注意,Map使用对象标识来查找值,因此c.get({key: false})将不起作用。


哪种方式真正取决于您的需求。

答案 2 :(得分:2)

您可能会看看c,在那里您看到a.toString()的结果

const a = { key: true }
const b = { key: false }
const c = { [a]: '1', [b]: '2' }

console.log(c);
console.log(c[a], c[b]);

为解决此问题,您可以使用JSON字符串

const a = { key: true }
const b = { key: false }
const c = { [JSON.stringify(a)]: '1', [JSON.stringify(b)]: '2' }

console.log(c);
console.log(c[JSON.stringify(a)], c[JSON.stringify(b)]);

尤其对于对象作为键,可以使用WeakMap

const a = { key: true }
const b = { key: false }
const c = new WeakMap([[a, '1'], [b, '2']]);

console.log(c.get(a), c.get(b));

答案 3 :(得分:1)

JavaScript对象键是字符串(或者可选地是Symbols,但这既不是这里也不是那里)。如果您使用console.log(c),您会看到它是{[object Object]:“ 2”},因为[a]和[b] .toString()都是“ [object Object]”

至于“修复”……我不明白您要实现的目标,抱歉,我无法为您提供帮助。