Se si sta programmando in un ambiente compatibile con ES6 (come node.js, un browser specifico con le funzionalità ES6 necessarie o la trasplicazione del codice ES6 per il proprio ambiente), è possibile utilizzare l' Setoggetto incorporato in ES6 . Ha delle ottime capacità e può essere usato come è nel tuo ambiente.
Per molte cose semplici in un ambiente ES5, l'utilizzo di un oggetto funziona molto bene. Se objè il tuo oggetto ed Aè una variabile che ha il valore su cui vuoi operare nel set, allora puoi farlo:
Codice di inizializzazione:
// 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};
Domanda 1: È Anell'elenco:
if (A in obj) {
// put code here
}
Domanda 2: Elimina 'A' dall'elenco se è presente:
delete obj[A];
Domanda 3: aggiungi "A" all'elenco se non era già presente
obj[A] = true;
Per completezza, il test per stabilire se Aè nell'elenco è un po 'più sicuro con questo:
if (Object.prototype.hasOwnProperty.call(obj, A))
// put code here
}
a causa del potenziale conflitto tra metodi integrati e / o proprietà sull'oggetto base come la constructorproprietà.
Barra laterale su ES6: l'attuale versione funzionante di ECMAScript 6 o qualcosa chiamato ES 2015 ha un oggetto Set incorporato . Ora è implementato in alcuni browser. Poiché la disponibilità del browser cambia nel tempo, è possibile cercare la riga Setin questa tabella di compatibilità ES6 per vedere lo stato corrente della disponibilità del browser.
Un vantaggio dell'oggetto Set incorporato è che non obbliga tutte le chiavi a una stringa come fa l'Oggetto, quindi puoi avere sia 5 che "5" come chiavi separate. Inoltre, puoi persino usare Oggetti direttamente nel set senza una conversione di stringhe. Ecco un articolo che descrive alcune delle funzionalità e la documentazione di MDN sull'oggetto Set.
Ora ho scritto un polyfill per l'oggetto set ES6 in modo da poter iniziare a usarlo ora e rimanderà automaticamente all'oggetto set incorporato se il browser lo supporta. Questo ha il vantaggio di scrivere codice compatibile ES6 che funzionerà fino a IE7. Ma ci sono alcuni aspetti negativi. L'interfaccia del set ES6 sfrutta gli iteratori ES6 in modo che tu possa fare cose del genere for (item of mySet)e itererà automaticamente attraverso il set per te. Tuttavia, questo tipo di funzionalità del linguaggio non può essere implementata tramite polyfill. È ancora possibile iterare un set ES6 senza utilizzare le nuove funzionalità delle lingue ES6, ma francamente senza le nuove funzionalità della lingua, non è conveniente come l'altra interfaccia impostata che includo di seguito.
Puoi decidere quale funziona meglio per te dopo aver visto entrambi. Il polyfill set ES6 è qui: https://github.com/jfriend00/ES6-Set .
Cordiali saluti, nei miei test ho notato che l'implementazione di Firefox v29 Set non è completamente aggiornata sulla bozza corrente delle specifiche. Ad esempio, non è possibile concatenare .add()chiamate di metodo come descritto nelle specifiche e supportate da my polyfill. Probabilmente si tratta di una specifica in movimento in quanto non ancora finalizzata.
Oggetti set predefiniti: se si desidera un oggetto già costruito con metodi per operare su un set che è possibile utilizzare in qualsiasi browser, è possibile utilizzare una serie di diversi oggetti precostruiti che implementano diversi tipi di set. C'è un miniSet che è un piccolo codice che implementa le basi di un oggetto set. Ha anche un oggetto set più ricco di funzionalità e diverse derivazioni tra cui un dizionario (memorizziamo / recuperiamo un valore per ogni chiave) e un ObjectSet (manteniamo un insieme di oggetti - oggetti JS o oggetti DOM in cui fornire il funzione che genera una chiave univoca per ognuno o ObjectSet genererà la chiave per te).
Ecco una copia del codice per il miniSet (il codice più aggiornato è qui su 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;