Понимание символов ES6

Я был вокруг блока, когда дело доходило до языков, работая со всем от С# до Lisp до Scala до Haskell, и на всех языках, которые их поддерживали, символы действовали почти одинаково; то есть любые два символа с одинаковым именем гарантированы одинаковыми, поскольку они являются одноэлементными объектами.

Ракетка: (equal? 'foo 'foo) true

Общий Lisp: (eq 'foo 'foo) true

Ruby: :foo == :foo true

Scala: 'foo == 'foo true

ES6: Symbol('foo') === Symbol('foo') false

Преимущество символов, являющихся одноточечными, очевидно: вы можете использовать их в картах/словарях, не рискуя своим ключом, не равным вашему вводу, потому что язык внезапно решил хэш по-другому (смотря на вас, Ruby)

Итак, почему ECMAScript 6 использует другой подход к этому, и как я могу обойти его?

Ответы

Ответ 1

Вы можете (сортировать) получить действие символов, "узнаваемых" по имени, используя зарегистрированные (глобальные) символы:

var s1 = Symbol.for("foo");
var s2 = Symbol.for("foo");
s1 === s2; // true

Конечно, вы можете создать собственный реестр Symbol, с экземпляром Map или простым объектом.

edit — Я добавлю, что намерение необязательного параметра строки при создании нового экземпляра Symbol - предоставить способ определения смысла и цели символа для программиста. Без этой строки Символ отлично работает как символ, но если вы отбрасываете объект в отладчике, то свойства, созданные такими анонимными экземплярами Symbol, являются просто значениями. Если вы сохраняете числовые свойства объекта с помощью символов Symbol, вы увидите только некоторые цифры, и это будет путать. Строка описания, связанная с экземплярами Symbol, дает справочную информацию программиста без ущерба для уникальности символа как ключевого значения.

Наконец, вы всегда можете сравнить результат вызова .toString() на двух аналогично построенных экземплярах Symbol. Я подозреваю, что эта практика будет считаться сомнительной, но вы можете это сделать.

изменить больше — мне приходит в голову, что тот факт, что поведение по умолчанию создания Symbol в JavaScript делает тип более полезным, чем, скажем, атомы в Erlang или ключи в Clojure. Поскольку язык по умолчанию по умолчанию гарантирует уникальность, основная проблема столкновения пространства имен решена довольно красиво. По-прежнему возможно работать с "хорошо известными" символами, но наличие уникальных значений, не беспокоящих о конфликтах с другим кодом, которые также могут избежать столкновения, приятно. JavaScript имеет несколько уникальную и, безусловно, однозначно распространенную и неконтролируемую проблему глобального пространства имен, которая может быть загрязнена кодом, которого программист даже не знает, потому что код может столкнуться в среде браузера из-за действий стороны, отличной от, и неизвестно, произвольное количество архитекторов программного обеспечения.