Quiero producir un hash derivado de la referencia de un Object
y luego asociar la cadena hash al objeto mismo en un diccionario.
He oído hablar de object-hash e intenté la siguiente implementación:
const objectHash = require('object-hash'); class A { a: string; constructor() { this.a = '1'; } } let a = new A(); let ab = new A(); console.log(objectHash(a)); // 712041d72943c4794bb23d1d455e17b3a4ea17f5 console.log(objectHash(ab));// 712041d72943c4794bb23d1d455e17b3a4ea17f5
A pesar de que a
y ab
son objetos diferentes (aunque instancias de la misma clase), el hash producido es igual, lo que no es el resultado esperado. Esto se debe a que la biblioteca genera valores de objeto en lugar de referencia de objeto .
Resultado Esperado
let foo = new A(); let bar = new A(); const fooH = objectHash(foo); <-- Produces a unique hash string representing the reference of "foo" const barH = objectHash(bar); <-- Produces a unique hash string representing the reference of "bar" let objects = { fooH: foo, barH: bar }
Esto probablemente podría lograrse en C ++ o C # mediante el uso de punteros y direcciones , pero ¿qué pasa con Javascript? Si alguien puede guiarme en el camino correcto para encapsular la referencia de un objeto en una cadena, se lo agradecería.
No es posible obtener la referencia de un objeto en JavaScript para calcular un hash del mismo. La referencia es un valor interno del motor que normalmente no está expuesto.
Sin embargo, si desea indexar algunos datos contra un objeto, puede usar un Map
, ya que las claves pueden ser cualquier valor de JavaScript arbitrario, lo que permite objetos. Dado que los objetos son únicos durante la comparación, eso significa que el mismo objeto devuelve el valor:
class A { constructor() { this.a = '1'; } } const foo = new A(); const bar = new A(); const map = new Map() .set(foo, "hello") .set(bar, "world"); console.log(map.get(foo), map.get(bar));
JavaScript también tiene un WeakMap
: solo permite objetos como claves, pero a su vez solo tiene una referencia débil a ellos. Esto significa que una vez que se elimine cualquier otra referencia a la clave, WeakMap
no evitará que el objeto sea recolectado como basura.
Los mapas, y especialmente los WeakMaps, son una forma viable de extender objetos extraños sin tener que anidarlos en su propia jerarquía. Aquí hay una demostración rápida
import {a, b} from 'foreign'; const extension = new WeakMap() extension.set(a, { myProperty1: true, myProperty2: 40, myProperty3: "hello", }); extension.set(b, { myProperty1: false, myProperty2: 2, myProperty3: "world" });
Aquí tenemos algunos objetos extraños a
, b
no los controlamos y los ampliamos con nuestras propias propiedades sin necesidad de cambiarlos o clonarlos . Mirar el objeto en el WeakMap
da las propiedades extendidas.
Ver una descripción más detallada por Benjamin Gruenbaum
Para mayor referencia, un Set
y un WeakSet
exhiben las mismas propiedades que un Mapa y un WeakMap, respectivamente, en términos de almacenamiento de objetos. Sin embargo, ellos sin un valor extra para el objeto. Eso puede ser útil, por ejemplo, para realizar un seguimiento de los objetos vistos . Qué controladores de eventos se han activado, o qué nodos de un gráfico se han visitado, y similares.