Si está programando en un entorno compatible con ES6 (como node.js, un navegador específico con las capacidades de ES6 que necesita o transpilando el código de ES6 para su entorno), puede usar el Setobjeto integrado en ES6 . Tiene capacidades muy agradables y se puede usar como está en su entorno.
Para muchas cosas simples en un entorno ES5, usar un objeto funciona muy bien. Si objes su objeto y Aes una variable que tiene el valor con el que desea operar en el conjunto, puede hacer lo siguiente:
Código de inicialización:
// create empty object
var obj = {};
// or create an object with some items already in it
var obj = {"1":true, "2":true, "3":true, "9":true};
Pregunta 1: está Aen la lista:
if (A in obj) {
// put code here
}
Pregunta 2: Eliminar 'A' de la lista si está allí:
delete obj[A];
Pregunta 3: Agregue 'A' a la lista si aún no estaba allí
obj[A] = true;
Para completar, la prueba de si Aestá en la lista es un poco más segura con esto:
if (Object.prototype.hasOwnProperty.call(obj, A))
// put code here
}
debido a un posible conflicto entre los métodos integrados y / o las propiedades en el Objeto base, como la constructorpropiedad.
Barra lateral en ES6: la versión de trabajo actual de ECMAScript 6 o algo llamado ES 2015 tiene un objeto Set incorporado . Se implementa ahora en algunos navegadores. Dado que la disponibilidad del navegador cambia con el tiempo, puede consultar la línea Seten esta tabla de compatibilidad de ES6 para ver el estado actual de la disponibilidad del navegador.
Una ventaja del objeto Set incorporado es que no obliga a todas las teclas a una cadena como lo hace el Objeto, por lo que puede tener tanto 5 como "5" como teclas separadas. E incluso puede usar objetos directamente en el conjunto sin una conversión de cadena. Aquí hay un artículo que describe algunas de las capacidades y la documentación de MDN sobre el objeto Set.
Ahora he escrito un polyfill para el objeto de conjunto ES6 para que pueda comenzar a usarlo ahora y se transferirá automáticamente al objeto de conjunto incorporado si el navegador lo admite. Esto tiene la ventaja de que está escribiendo un código compatible con ES6 que funcionará desde IE7. Pero, hay algunas desventajas. La interfaz del conjunto ES6 aprovecha los iteradores ES6 para que pueda hacer cosas como for (item of mySet)y automáticamente iterará a través del conjunto por usted. Pero, este tipo de función de lenguaje no se puede implementar a través de polyfill. Todavía puede iterar un conjunto ES6 sin usar las nuevas funciones de idiomas ES6, pero, francamente, sin las nuevas funciones de idioma, no es tan conveniente como la otra interfaz de conjunto que incluyo a continuación.
Puedes decidir cuál funciona mejor para ti después de mirar a ambos. El polyfill del conjunto ES6 está aquí: https://github.com/jfriend00/ES6-Set .
Para su información, en mis propias pruebas, me di cuenta de que la implementación de Firefox v29 Set no está completamente actualizada en el borrador actual de la especificación. Por ejemplo, no puede encadenar .add()llamadas de método como lo describe la especificación y mi polyfill admite. Probablemente se trate de una especificación en movimiento, ya que aún no está finalizada.
Objetos de conjunto preconstruido: si desea un objeto ya construido que tenga métodos para operar en un conjunto que pueda usar en cualquier navegador, puede usar una serie de diferentes objetos preconstruidos que implementan diferentes tipos de conjuntos. Hay un miniSet que es un código pequeño que implementa los conceptos básicos de un objeto establecido. También tiene un objeto de conjunto más rico en funciones y varias derivaciones que incluyen un Diccionario (le permite almacenar / recuperar un valor para cada clave) y un ObjectSet (le permite mantener un conjunto de objetos, ya sea objetos JS u objetos DOM donde puede suministrar el función que genera una clave única para cada uno o el ObjectSet generará la clave para usted).
Aquí hay una copia del código para el miniSet (el código más actualizado es aquí en github ).
"use strict";
//-------------------------------------------
// Simple implementation of a Set in javascript
//
// Supports any element type that can uniquely be identified
// with its string conversion (e.g. toString() operator).
// This includes strings, numbers, dates, etc...
// It does not include objects or arrays though
// one could implement a toString() operator
// on an object that would uniquely identify
// the object.
//
// Uses a javascript object to hold the Set
//
// This is a subset of the Set object designed to be smaller and faster, but
// not as extensible. This implementation should not be mixed with the Set object
// as in don't pass a miniSet to a Set constructor or vice versa. Both can exist and be
// used separately in the same project, though if you want the features of the other
// sets, then you should probably just include them and not include miniSet as it's
// really designed for someone who just wants the smallest amount of code to get
// a Set interface.
//
// s.add(key) // adds a key to the Set (if it doesn't already exist)
// s.add(key1, key2, key3) // adds multiple keys
// s.add([key1, key2, key3]) // adds multiple keys
// s.add(otherSet) // adds another Set to this Set
// s.add(arrayLikeObject) // adds anything that a subclass returns true on _isPseudoArray()
// s.remove(key) // removes a key from the Set
// s.remove(["a", "b"]); // removes all keys in the passed in array
// s.remove("a", "b", ["first", "second"]); // removes all keys specified
// s.has(key) // returns true/false if key exists in the Set
// s.isEmpty() // returns true/false for whether Set is empty
// s.keys() // returns an array of keys in the Set
// s.clear() // clears all data from the Set
// s.each(fn) // iterate over all items in the Set (return this for method chaining)
//
// All methods return the object for use in chaining except when the point
// of the method is to return a specific value (such as .keys() or .isEmpty())
//-------------------------------------------
// polyfill for Array.isArray
if(!Array.isArray) {
Array.isArray = function (vArg) {
return Object.prototype.toString.call(vArg) === "[object Array]";
};
}
function MiniSet(initialData) {
// Usage:
// new MiniSet()
// new MiniSet(1,2,3,4,5)
// new MiniSet(["1", "2", "3", "4", "5"])
// new MiniSet(otherSet)
// new MiniSet(otherSet1, otherSet2, ...)
this.data = {};
this.add.apply(this, arguments);
}
MiniSet.prototype = {
// usage:
// add(key)
// add([key1, key2, key3])
// add(otherSet)
// add(key1, [key2, key3, key4], otherSet)
// add supports the EXACT same arguments as the constructor
add: function() {
var key;
for (var i = 0; i < arguments.length; i++) {
key = arguments[i];
if (Array.isArray(key)) {
for (var j = 0; j < key.length; j++) {
this.data[key[j]] = key[j];
}
} else if (key instanceof MiniSet) {
var self = this;
key.each(function(val, key) {
self.data[key] = val;
});
} else {
// just a key, so add it
this.data[key] = key;
}
}
return this;
},
// private: to remove a single item
// does not have all the argument flexibility that remove does
_removeItem: function(key) {
delete this.data[key];
},
// usage:
// remove(key)
// remove(key1, key2, key3)
// remove([key1, key2, key3])
remove: function(key) {
// can be one or more args
// each arg can be a string key or an array of string keys
var item;
for (var j = 0; j < arguments.length; j++) {
item = arguments[j];
if (Array.isArray(item)) {
// must be an array of keys
for (var i = 0; i < item.length; i++) {
this._removeItem(item[i]);
}
} else {
this._removeItem(item);
}
}
return this;
},
// returns true/false on whether the key exists
has: function(key) {
return Object.prototype.hasOwnProperty.call(this.data, key);
},
// tells you if the Set is empty or not
isEmpty: function() {
for (var key in this.data) {
if (this.has(key)) {
return false;
}
}
return true;
},
// returns an array of all keys in the Set
// returns the original key (not the string converted form)
keys: function() {
var results = [];
this.each(function(data) {
results.push(data);
});
return results;
},
// clears the Set
clear: function() {
this.data = {};
return this;
},
// iterate over all elements in the Set until callback returns false
// myCallback(key) is the callback form
// If the callback returns false, then the iteration is stopped
// returns the Set to allow method chaining
each: function(fn) {
this.eachReturn(fn);
return this;
},
// iterate all elements until callback returns false
// myCallback(key) is the callback form
// returns false if iteration was stopped
// returns true if iteration completed
eachReturn: function(fn) {
for (var key in this.data) {
if (this.has(key)) {
if (fn.call(this, this.data[key], key) === false) {
return false;
}
}
}
return true;
}
};
MiniSet.prototype.constructor = MiniSet;