Подтвердить что ты не робот

Почему объект [ключ] не равен ключу, если ключ является объектом, в JavaScript?

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

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

console.log(c[a] === a);

Я проверил код выше и получаю false. Если я попробую console.log(c[a] === b), тогда будет напечатан true.

Почему?

4b9b3361

Ответ 1

Проблема здесь связана с тем, как установлены клавиши Object. Из MDN:

Параметры

nameValuePair1, nameValuePair2,... nameValuePairN

  • Пары имен (строк) и значений (любое значение), где имя отделяется от значения двоеточием.

Значение

  • Любое значение.

Доступ к объектным значениям (через соответствующий ключ) осуществляется тремя способами:

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

При использовании обозначения в виде кронштейна вам нужно учитывать разрыв... между скобками! Объекты устанавливают свои ключи и значения с помощью метода toString, если только они не передают строку (тогда нет точки в toString). При использовании точечной нотации они используют .key в качестве ключа.

Посмотрите на ваш случай:

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

Ответ 2

Объект не является допустимым ключом для объекта JavaScript, только строки

Итак, когда вы это сделаете:

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

Компилятор не может использовать a или b как ключ для c, как в c [a] или c [b].

Однако это не подводит, потому что JavaScript может обойти эту проблему. Сначала выясняется, что

  • Переменная - это объект и
  • У переменной есть toString -function

Таким образом, компилятор JavaScript вызовет toString() каждой из этих переменных. И по умолчанию Object.prototype.toString возвращает "[object Object]" -string, потому что реализация является реализацией по умолчанию, которая делает это, и это значение становится новым ключом

c["[object Object]"] = a;
c["[object Object]"] = b; // overrides the previous

Это не то, что вы хотели. Проблема в том, что toString будет по умолчанию возвращать всегда одно и то же значение, поэтому настройки всегда будут поступать на один и тот же ключ.

Чтобы продемонстрировать, что toString на самом деле является проблемой, вы действительно можете сделать ужасный чит, чтобы каждый объект возвращал уникальную строку

// don't do this!!! 
(function() {
  var id=1;
  Object.prototype.toString = function() {
   if(!this._id) this._id = id++;
   return "Object"+this._id;
  }
}());

После этого ключ c [a] будет c [ "Object1" ], а c [b] будет c [ "Object2" ] и т.д.... и c [a] == a и c [ b] == b работают так, как ожидалось, но в реальной жизни это не очень хорошее решение.

Допустимым способом решения этого может быть либо использование другого ключа, возможно, идентификатора, назначенного объекту типа c [a.id] = a, или для использования объекта карты ES6, где можно использовать любое значение, включая объекты. как ключ.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

Объект Map - это простая карта ключа/значения. Любое значение (оба объекта и примитивные значения) могут использоваться как ключ или значение.

Ответ 3

Я экспериментировал с ним немного, и @royhowie может быть прав. Как вы можете видеть в этой реализации, я переключил порядок назначений, а затем c [a] == a дал истину.

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

Выход: true