По сути, я пытаюсь создать объект из уникальных объектов, набор. У меня была блестящая идея просто использовать объект JavaScript с объектами для имен свойств. Такие как,
set[obj] = true;
Это работает, до определенного момента. Он отлично работает со строками и числами, но с другими объектами все они, похоже, "хэшируют" одно и то же значение и имеют доступ к одному и тому же свойству. Есть ли какой-то способ, которым я могу генерировать уникальное значение хеш-функции для объекта? Как строки и числа делают это, я могу переопределить то же самое поведение?
JSON.stringify(obj)
илиobj.toSource()
может работать для вас в зависимости от проблемы и целевой платформы.toSource
не работай в Chrome, кстатиОтветы:
Объекты JavaScript могут использовать только строки в качестве ключей (все остальное преобразуется в строку).
В качестве альтернативы вы можете поддерживать массив, который индексирует рассматриваемые объекты, и использовать его индексную строку в качестве ссылки на объект. Что-то вроде этого:
Очевидно, это немного многословно, но вы могли бы написать пару методов, которые справятся с этим, и получат и установят все, что угодно.
Редактировать:
Это поднимает еще один интересный момент; Вы можете определить метод toString для объектов, которые хотите хэшировать, и это может сформировать их хеш-идентификатор.
источник
Если вам нужна функция hashCode (), подобная Java в JavaScript, она ваша:
Это способ реализации в Java (побитовый оператор).
Обратите внимание, что hashCode может быть положительным и отрицательным, и это нормально, см. HashCode с отрицательными значениями . Итак, вы можете рассмотреть возможность использования
Math.abs()
вместе с этой функцией.источник
char
- зарезервированное слово в JS и может вызвать некоторые проблемы. Какое-то другое имя было бы лучше.pickOne["helloo".hashCode() % 20]
массивpickOne
с 20 элементами. Я получил,undefined
потому что хеш-код отрицательный, так что это пример, в котором кто-то (я) неявно предполагал положительные хеш-коды.Самый простой способ сделать это - дать каждому из ваших объектов свой уникальный
toString
метод:У меня была та же проблема, и это решило ее идеально для меня с минимальными усилиями, и было намного проще, чем заново реализовать какой-то жирный стиль Java
Hashtable
и добавлятьequals()
иhashCode()
к вашим объектным классам. Просто убедитесь, что вы не вставляете строку '<#MyObject: 12> в ваш хеш, иначе это сотрет запись для вашего выходящего объекта с этим идентификатором.Теперь все мои хэши совершенно холодные. Я также только что опубликовал запись в блоге несколько дней назад на эту тему .
источник
equals()
иhashCode()
так, чтобы два эквивалентных объекта имели одинаковое хеш-значение. Использование описанного выше метода означает, что каждый экземплярMyObject
будет иметь уникальную строку, что означает, что вам нужно будет сохранить ссылку на этот объект, чтобы когда-либо получить правильное значение с карты. Наличие ключа не имеет смысла, потому что оно не имеет ничего общего с уникальностью объекта. ПолезнаяtoString()
функция должна быть реализована для конкретного типа объекта, который вы используете в качестве ключа.toString
для объектов так, чтобы он напрямую отображал отношение эквивалентности, чтобы два объекта создавали одинаковую строку, если они считаются «равными».toString()
чтобы позволить вам использоватьObject
какSet
. Я думаю, что я неправильно понял ваш ответ как попытку предоставить общее решение, чтобы избежать написанияtoString()
эквивалентаequals()
илиhashCode()
в каждом конкретном случае.То, что вы описали, покрыто Harmony WeakMaps , частью спецификации ECMAScript 6 (следующая версия JavaScript). То есть: набор, где ключи могут быть чем угодно (включая неопределенные) и не перечисляются.
Это означает, что невозможно получить ссылку на значение, если у вас нет прямой ссылки на ключ (любой объект!), Который ссылается на него. Это важно по ряду причин реализации движка, связанных с эффективностью и сборкой мусора, но это также очень круто, так как позволяет использовать новую семантику, такую как отзывные разрешения на доступ и передачу данных без раскрытия отправителя данных.
От MDN :
Слабые карты доступны в текущих Firefox, Chrome и Edge. Они также поддерживаются в Node v7 и v6 с
--harmony-weak-maps
флагом.источник
Map
?var m = new Map();m.set({},"abc"); console.log(m.get({}) //=>undefined
Это работает, только если у вас есть та же переменная, на которую вы изначально ссылались в команде set. EGvar m = new Map();a={};m.set(a,"abc"); console.log(m.get(a) //=>undefined
Решение, которое я выбрал, похоже на решение Дэниела, но вместо того, чтобы использовать фабрику объектов и переопределить toString, я явно добавляю хэш к объекту, когда он сначала запрашивается через функцию getHashCode. Немного грязно, но лучше для моих нужд :)
источник
Object.defineProperty
сenumerable
установленным наfalse
, так что вы не врезаться никакихfor .. in
петель.Для моей конкретной ситуации меня интересует только равенство объекта в том, что касается ключей и примитивных значений. Решением, которое работало для меня, было преобразование объекта в его JSON-представление и использование его в качестве хэша. Существуют ограничения, такие как порядок определения ключа, который может быть непоследовательным; но, как я сказал, это сработало для меня, потому что все эти объекты создавались в одном месте.
источник
Некоторое время назад я собрал небольшой модуль JavaScript для создания хеш-кодов для строк, объектов, массивов и т. Д. (Я просто передал его в GitHub :))
Использование:
источник
var hash1 = Hashcode.value({ a: 1, b: 2 }); var hash2 = Hashcode.value({ a: 2, b: 1 }); console.log(hash1, hash2);
записывают в журнал2867874173
2867874173
Спецификация JavaScript определяет доступ к индексированным свойствам как выполнение преобразования toString для имени индекса. Например,
такой же как
Это необходимо как в JavaScript
такой же как
И да, это меня тоже огорчает :-(
источник
В ECMAScript 6 теперь есть функция,
Set
которая работает так, как вам хочется: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SetОн уже доступен в последних версиях Chrome, FF и IE11.
источник
Ссылка: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
Вы можете использовать символ Es6 для создания уникального ключа и доступа к объекту. Каждое значение символа, возвращаемое из Symbol (), является уникальным. Значение символа может использоваться в качестве идентификатора для свойств объекта; это единственная цель типа данных.
источник
Вот мое простое решение, которое возвращает уникальное целое число.
источник
hashcode({a:1, b:2}) === hashcode({a:2, b:1})
и многих других конфликтов.Основываясь на заголовке, мы можем генерировать сильные хэши с помощью js, его можно использовать для генерации уникального хеша из объекта, массива параметров, строки или чего-либо еще.
Позже для индексации это позволит избежать возможных ошибок сопоставления, позволяя при этом извлекать индекс из параметров (избегать поиска / зацикливания объекта и т. Д.):
Выше приведен вывод в моем браузере, он должен быть одинаковым и для вас ( это правда? ):
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#Converting_a_digest_to_a_hex_string
источник
Мое решение вводит статическую функцию для глобального
Object
объекта.Я думаю, что это удобнее с другими функциями управления объектами в JavaScript.
источник
Я постараюсь пойти немного глубже, чем другие ответы.
Даже если бы у JS была лучшая поддержка хеширования, он не мог бы магически все хешировать, во многих случаях вам придется определять свою собственную хеш-функцию. Например, Java имеет хорошую поддержку хеширования, но вам все еще нужно подумать и поработать.
Одна проблема связана с термином хэш / хэш-код ... существует криптографическое хеширование и некриптографическое хеширование. Другая проблема заключается в том, что вы должны понимать, почему хеширование полезно и как оно работает.
Когда мы говорим о хешировании в JavaScript или Java, большую часть времени мы говорим о некриптографическом хешировании, обычно о хешировании для hashmap / hashtable (если мы не работаем над аутентификацией или паролями, которые вы могли бы выполнять на стороне сервера, используя NodeJS. ..).
Это зависит от того, какие данные у вас есть и чего вы хотите достичь.
Ваши данные имеют некоторую естественную «простую» уникальность:
Ваши данные имеют некоторую естественную «составную» уникальность:
Вы не представляете, какими будут ваши данные:
Не существует магически эффективного метода хеширования неизвестных данных, в некоторых случаях это довольно просто, в других случаях вам, возможно, придется подумать дважды. Таким образом, даже если JavaScript / ECMAScript добавляет дополнительную поддержку, для этой проблемы не существует волшебного решения.
На практике вам нужны две вещи: достаточно уникальности, достаточно скорости
В дополнение к этому здорово иметь: «хэш-код равен, если объекты равны»
источник
Если вы действительно хотите установить поведение (я знаю Java), вам будет сложно найти решение в JavaScript. Большинство разработчиков рекомендуют уникальный ключ для представления каждого объекта, но это не так, как установлено, так как вы можете получить два идентичных объекта каждый с уникальным ключом. Java API выполняет проверку на наличие дублирующихся значений путем сравнения значений хеш-кода, а не ключей, и, поскольку в JavaScript отсутствует представление значений хэш-кода объектов в JavaScript, практически невозможно сделать то же самое. Даже библиотека Prototype JS допускает этот недостаток, когда говорит:
http://www.prototypejs.org/api/hash
источник
В дополнение к ответу без век, вот функция, которая возвращает воспроизводимый уникальный идентификатор для любого объекта:
Как вы можете видеть, он использует список для поиска, который очень неэффективен, однако это лучшее, что я смог найти на данный момент.
источник
Если вы хотите использовать объекты в качестве ключей, вам нужно перезаписать их метод toString, как некоторые уже упоминали здесь. Все хеш-функции в порядке, но они работают только для тех же объектов, но не для одинаковых объектов.
Я написал небольшую библиотеку, которая создает хэши из объектов, которые вы можете легко использовать для этой цели. Объекты могут даже иметь другой порядок, хэши будут одинаковыми. Внутренне вы можете использовать различные типы для вашего хэша (djb2, md5, sha1, sha256, sha512, palemd160).
Вот небольшой пример из документации:
Пакет можно использовать как в браузере, так и в Node-Js.
Репозиторий: https://bitbucket.org/tehrengruber/es-js-hash
источник
Если вы хотите иметь уникальные значения в объекте поиска, вы можете сделать что-то вроде этого:
Создание объекта поиска
Настройка функции хэш-кода
объект
массив
Другие типы
Конечный результат
{ 1337: true, 01132337: true, StackOverflow: true }
Обратите внимание, что
getHashCode
не возвращает никакого значения, когда объект или массив пустЭто похоже на решение @ijmacd, только
getHashCode
не имеетJSON
зависимости.источник
Я объединил ответы от век и КимХа.
Ниже приведен сервис angularjs, который поддерживает числа, строки и объекты.
Пример использования:
Вывод
объяснение
Как видите, в основе службы лежит хеш-функция, созданная KimKha. Я добавил типы в строки, чтобы структура объекта также влияла на окончательное значение хеш-функции. Ключи хэшируются для предотвращения столкновений массивов | объектов.
Сравнение объектов без век используется для предотвращения бесконечной рекурсии путем самообращения объектов.
использование
Я создал этот сервис, чтобы у меня мог быть сервис ошибок, к которому обращаются объекты. Таким образом, одна служба может зарегистрировать ошибку с данным объектом, а другая может определить, были ли обнаружены какие-либо ошибки.
т.е.
JsonValidation.js
UserOfData.js
Это вернуло бы:
Пока
Это вернется
источник
Просто используйте скрытое секретное свойство с
defineProperty
enumerable: false
Работает очень быстро :
источник