在JavaScript中,如果key是一个对象,为什么object[key]不等于key?

在JavaScript中,如果key是一个对象,为什么object[key]不等于key?,javascript,Javascript,我测试了上面的代码,得到false。如果我尝试console.log(c[a]==b),则会打印true 为什么?这里的问题与如何设置对象的键有关。发件人: 参数 nameValuePair1,nameValuePair2。。。nameValuePairN 名称(字符串)和值(任意值)对,其中名称与值之间用冒号分隔 值 任何价值 可以通过三种方式访问对象的值(通过相应的键): var a = new Object; var b = new Object; var c = new Obje

我测试了上面的代码,得到
false
。如果我尝试
console.log(c[a]==b)
,则会打印
true


为什么?

这里的问题与如何设置
对象的键有关。发件人:

参数 nameValuePair1,nameValuePair2。。。nameValuePairN

  • 名称(字符串)和值(任意值)对,其中名称与值之间用冒号分隔

  • 任何价值
可以通过三种方式访问对象的值(通过相应的键):

var a = new Object;
var b = new Object;
var c = new Object;

c[a] = a;
c[b] = b;

console.log(c[a] === a);
使用括号表示法时,需要注意括号之间的间隙!对象使用该方法设置它们的键和值,除非传递给它们一个字符串(那么
toString
)就没有意义了。使用点表示法时,他们使用
.key
作为键

让我们看看您的案例:

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
}
*/

我尝试了一点,royhowie可能是对的。正如您在这个实现中看到的,我切换了赋值的顺序,然后c[a]==a给出了一个true

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`)

输出:true

对象不是JavaScript对象的有效键,只有字符串是有效的

因此,当您这样做时:

var a = new Object;
var b = new Object;
var c = new Object;

//I switched the following lines of code
c[b]=b; 
c[a]=a;

console.log(c[a]===a);
编译器不能像在c[a]或c[b]中那样使用a或b作为c的键

但是,它不会失败,因为JavaScript可以解决这个问题。首先它发现

  • 变量是一个对象,并且
  • 该变量具有toString-函数
  • 因此,JavaScript编译器将调用每个变量的toString()。默认情况下,Object.prototype.toString它将返回“[Object Object]”-string,因为实现是执行该操作的默认实现,该值将成为新的键

    c[a] = a;
    c[b] = b;
    
    这不是你想要的。问题是toString在默认情况下将始终返回相同的值,因此assigments将始终指向相同的键

    为了证明toString实际上是个问题,您可以实际执行一个可怕的欺骗,使每个对象返回唯一的字符串

    c["[object Object]"] = a;
    c["[object Object]"] = b; // overrides the previous
    
    在此之后,c[a]的键将是c[“Object1”],c[b]的键将是c[“Object2”],依此类推。。。c[a]==a和c[b]==b的工作原理与预期一致,但在现实生活中,这并不是一个好的解决方案

    解决这个问题的一个可接受的方法是使用其他一些键,可能是分配给对象的ID,比如c[a.ID]=a,或者使用ES6映射对象,其中任何值(包括对象)都可以用作键

    映射对象是一个简单的键/值映射。任何值(对象和对象) 基本值)可以用作键或值


    你为什么要这样做?@VikashKesarwani-这是个好问题。很可能他把问题简化成一个简单的例子,它不像你在C++中所做的那样,这里是分配问题。对于这种你想做的自我披露的形式,没有解决方案
    c.a=a
    c['a']=a
    。这是用来设置属性名的,就像给它一个字符串一样
    c[a]
    将属性名称设置为与变量
    a
    的值相同。
    console.log(c)谜团解开了。这个问题很平常。正如我在上面的评论中提到的,自我披露的作业注释不是
    a.toString()
    字符串
    “[object object]”
    ?@slebetman您是对的;我在想JSON。我将修复这个问题(尽管这是同一个概念)@2pha您将要执行的
    c['[object]]={}
    ,这将使
    c
    数组保持不变,因为您是通过字符串而不是索引访问它的。@2pha我重写了我的答案,并试图使其更简洁。你写的东西正是发生的。是的,你的切换使情况完全不同。谢谢。现在这个问题更清楚了,但我仍然不知道如何使用你推荐的c[a.id]。这取决于你的意图,但如果你想从“哈希”c中查找对象,你可以为每个对象分配一些唯一的id,like obj.id=1234;然后将该值赋值为c,类似于c[obj.id]=obj;然后,如果要从散列中查找对象,请使用c[]或c[someObject.id]等进行搜索。
    // don't do this!!! 
    (function() {
      var id=1;
      Object.prototype.toString = function() {
       if(!this._id) this._id = id++;
       return "Object"+this._id;
      }
    }());