Se supone que WeakSet almacena elementos por referencia débil. Es decir, si ningún otro objeto 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 elimina 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 fallas de Traceur o me estoy perdiendo algo?
Y finalmente, ¿cuál es el uso práctico de WeakSet si ni siquiera podemos iterarlo ni obtener el tamaño actual?
no se elimina del WeakSet. ¿Porqué es eso?
Lo más probable es que el recolector de elementos no utilizados aún no se haya ejecutado. Sin embargo, dice que está utilizando Traceur, por lo que es posible que no sean compatibles correctamente. Me pregunto cómo la console puede mostrar el contenido de un WeakSet de todos modos.
¿Cuál es el punto de agregar objetos a WeakSets directamente?
No tiene absolutamente ningún sentido agregar objetos literales a WeakSet s.
¿Cuál es el uso práctico de WeakSet si ni siquiera podemos iterarlo ni obtener el tamaño actual?
Todo lo que puede obtener es un bit de información: ¿Está el objeto (o genéricamente, el valor) contenido en el conjunto?
Esto puede ser útil en situaciones en las que desea "etiquetar" objetos sin mutarlos (establecerles una propiedad). 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 trabaja con valores proporcionados por el usuario, sería recomendable 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 previene fugas) cuando se trata de una gran cantidad de datos que son perezosos (posiblemente incluso de forma asíncrona). ) producido.
Esta es una pregunta realmente difícil. Para ser completamente honesto, no tenía ni idea en el contexto de JavaScript , así que pregunté en esdiscuss y Domenic me dio una respuesta convincente.
Los WeakSets son útiles por razones de seguridad y validación . Si desea poder aislar una pieza 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 direct access to } makeRequest() { // do work } } Ahora, estoy escribiendo una plataforma de JavaScript. Mi plataforma le permite ejecutar JavaScript para hacer llamadas. Para hacer esas llamadas, necesita un ApiRequest . Solo quiero que haga ApiRequest con los objetos que le doy para que no pueda pasar por alto. cualquier restricción que tenga.
Sin embargo, por el 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 recolecten basura. Además de un cierre, se puede lograr cualquier cosa con métodos públicos como Object.getOwnPropertyNames u Object.getOwnSymbols . Así que me superas 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 tener un objeto ApiRequest válido para llamar al método makeRequest . Esto es imposible sin un WeakMap/WeakSet.
En resumen, los WeakMaps son útiles para escribir plataformas en JavaScript . Normalmente, este tipo de validación se realiza en el lado de C++, pero agregar estas funciones permitirá mover y hacer cosas en JavaScript.
(Por supuesto, todo lo que hace un WeakSet también lo puede hacer un WeakMap que asigna valores a true , 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
¿Suena más bastante familiar?
En algunas aplicaciones, los desarrolladores pueden necesitar implementar una forma rápida de iterar a través de una serie de datos que están contaminados por montones y montones de redundancia , pero desea elegir solo aquellos que no se han procesado antes (únicos) . 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.