nodejs new mdn mapa crear javascript ecmascript-6 traceur

javascript - new - set() js



ECMAScript 6: ¿para qué sirve WeakSet? (6)

Se supone que WeakSet almacena elementos por referencia débil. Es decir, si otra cosa no hace referencia a un objeto, debe limpiarse del WeakSet.

He escrito la siguiente prueba:

var weakset = new WeakSet(), numbers = [1, 2, 3]; weakset.add(numbers); weakset.add({name: "Charlie"}); console.log(weakset); numbers = undefined; console.log(weakset);

Aunque mi matriz [1, 2, 3] no está referenciada por nada, no se está eliminando del WeakSet. La consola imprime:

WeakSet {[1, 2, 3], Object {name: "Charlie"}} WeakSet {[1, 2, 3], Object {name: "Charlie"}}

¿Porqué es eso?

Además, tengo una pregunta más. ¿Cuál es el punto de agregar objetos a WeakSets directamente, así:

weakset.add({name: "Charlie"});

¿Son esos problemas técnicos de Traceur o me falta algo?

Y finalmente, ¿cuál es el uso práctico de WeakSet si ni siquiera podemos recorrerlo ni obtener el tamaño actual?


no se está eliminando del WeakSet. ¿Porqué es eso?

Lo más probable es que el recolector de basura aún no se haya ejecutado. Sin embargo, usted dice que está usando Traceur, por lo que puede ser que no sean compatibles. Me pregunto cómo la console puede mostrar el contenido de un WeakSet todos modos.

¿Cuál es el punto de agregar objetos a WeakSets directamente?

No tiene absolutamente ningún sentido agregar literales de objeto a WeakSet s.

¿Cuál es el uso práctico de WeakSet si ni siquiera podemos recorrerlo ni obtener el tamaño actual?

Todo lo que puede obtener es un poco de información: ¿está el objeto (o genéricamente, valor) contenido en el conjunto?

Esto puede ser útil en situaciones en las que desea "etiquetar" objetos sin mutarlos realmente (estableciendo una propiedad sobre ellos). Muchos algoritmos contienen algún tipo de condición "si ya se vio x " (una detección de ciclo JSON.stringify podría ser un buen ejemplo), y cuando trabaje con valores proporcionados por el WeakSet , sería aconsejable el uso de un Set / WeakSet . La ventaja de un WeakSet aquí es que su contenido se puede recolectar basura mientras su algoritmo aún se está ejecutando, por lo que ayuda a reducir el consumo de memoria (o incluso evita las fugas) cuando se trata de una gran cantidad de datos que son perezosamente (posiblemente incluso de forma asincrónica) ) producido.


Esta es una pregunta realmente difícil. Para ser completamente honesto, no tenía idea en el contexto de JavaScript, así que pregunté en esdiscuss y obtuve una respuesta convincente de Domenic .

Los WeakSets son útiles por razones de seguridad y validación . Si desea poder aislar un fragmento de JavaScript. Le permiten etiquetar un objeto para indicar que pertenece a un conjunto especial de objetos.

Digamos que tengo una clase ApiRequest :

class ApiRequest { constructor() { // bring object to a consistent state, use platform code you have no cirect access to } makeRequest() { // do work } }

Ahora, estoy escribiendo una plataforma JavaScript: mi plataforma le permite ejecutar JavaScript para realizar llamadas, para realizar esas llamadas necesita una ApiRequest . Solo quiero que haga ApiRequest s con los objetos que le doy para que no pueda omitirlas. cualquier restricción que tenga en su lugar.

Sin embargo, en este momento nada te impide hacer:

ApiRequest.prototype.makeRequest.call(null, args); // make request as function Object.create(ApiRequest.prototype).makeRequest(); // no initialization function Foo(){}; Foo.prototype = ApiRequest.prototype; new Foo().makeRequest(); // no super

Y así sucesivamente, tenga en cuenta que no puede mantener una lista normal o una matriz de objetos ApiRequest ya que eso evitaría que se recojan basura. Además de un cierre, se puede lograr cualquier cosa con métodos públicos como Object.getOwnPropertyNames o Object.getOwnSymbols . Así que me atacas y haces:

const requests = new WeakSet(); class ApiRequest { constructor() { requests.add(this); } makeRequest() { if(!request.has(this)) throw new Error("Invalid access"); // do work } }

Ahora, no importa lo que haga, debo mantener un objeto ApiRequest válido para invocar el método makeRequest . Esto es imposible sin un WeakMap / WeakSet.

En resumen, WeakMaps es útil para escribir plataformas en JavaScirpt . Normalmente, este tipo de validación se realiza en el lado de C ++, pero agregar estas características permitirá mover y hacer cosas en JavaScript.

(Por supuesto, todo lo que un WeakSet hace un WeakMap que asigna valores a true también puede hacerlo, pero eso es cierto para cualquier construcción de mapa / conjunto)

(Como sugiere la respuesta de Bergi, nunca hay una razón para agregar un objeto literal directamente a un WeakMap o un WeakSet )


Por definición, WeakSet tiene solo tres funcionalidades clave

  • Vincular débilmente un objeto al conjunto
  • Eliminar un enlace a un objeto del conjunto
  • Compruebe si un objeto ya se ha vinculado al conjunto

¿Suena más familiar?

En algunas aplicaciones, los desarrolladores pueden necesitar implementar una forma rápida de iterar a través de una serie de datos contaminados por montones y montones de redundancia, pero desea elegir solo aquellos que no se hayan procesado antes (único) . WeakSet podría ayudarte. Vea un ejemplo a continuación:

var processedBag = new WeakSet(); var nextObject = getNext(); while (nextObject !== null){ // Check if already processed this similar object? if (!processedBag.has(nextObject)){ // If not, process it and memorize process(nextObject); processedBag.add(nextObject); } nextObject = getNext(); }

Una de las mejores estructuras de datos para la aplicación anterior es el filtro Bloom, que es muy bueno para un tamaño de datos masivo. Sin embargo, también puede aplicar el uso de WeakSet para este propósito.


Su consola probablemente mostraba incorrectamente el contenido debido al hecho de que la recolección de basura aún no se realizó. Por lo tanto, dado que el objeto no era basura recolectada, mostraría que el objeto todavía está en punto débil.

Si realmente desea ver si un conjunto débil todavía tiene una referencia a un determinado objeto, utilice el método WeakSet.prototype.has() . Este método, como su nombre lo indica, devuelve un valor boolean indica si el objeto todavía existe en el conjunto débil.

Ejemplo:

var weakset = new WeakSet(), numbers = [1, 2, 3]; weakset.add(numbers); weakset.add({name: "Charlie"}); console.log(weakset.has(numbers)); numbers = undefined; console.log(weakset.has(numbers));


Un conjunto o mapa "débil" es útil cuando necesita mantener una colección arbitraria de cosas, pero no desea que su presencia en la colección impida que esas cosas se recojan si la memoria se agota. (Si se produce recolección de basura, los objetos "cosechados" desaparecerán silenciosamente de la colección, por lo que puede saber si se han ido).

Son excelentes, por ejemplo, para su uso como caché de búsqueda: "¿ya recuperé este registro recientemente?" Cada vez que recupere algo, póngalo en el mapa, sabiendo que el recolector de basura JavaScript será el responsable de "recortar la lista" para usted, y que lo hará automáticamente en respuesta a las condiciones de memoria prevalecientes (que puede '' t anticipar razonablemente).

El único inconveniente es que estos tipos no son "enumerables". No puede iterar sobre una lista de entradas, probablemente porque esto probablemente "tocaría" esas entradas y así frustraría el propósito. Pero, ese es un pequeño precio a pagar (y podría , si es necesario, "codificarlo").


WeakSet es una simplificación de WeakMap para que su valor siempre sea booleano verdadero. Le permite etiquetar objetos JavaScript para que solo haga algo con ellos una vez o para mantener su estado con respecto a un determinado proceso. En teoría, ya que no necesita mantener un valor, debería usar un poco menos de memoria y funcionar un poco más rápido que WeakMap.

var [touch, untouch] = (() => { var seen = new WeakSet(); return [ value => seen.has(value)) || (seen.add(value), !1), value => !seen.has(value) || (seen.delete(value), !1) ]; })(); function convert(object) { if(touch(object)) return; extend(object, yunoprototype); // Made up. }; function unconvert(object) { if(untouch(object)) return; del_props(object, Object.keys(yunoprototype)); // Never do this IRL. };