Nếu bạn đang lập trình trong môi trường có khả năng ES6 (chẳng hạn như node.js, một trình duyệt cụ thể có khả năng ES6 bạn cần hoặc dịch mã ES6 cho môi trường của bạn), thì bạn có thể sử dụng Setđối tượng được tích hợp trong ES6 . Nó có khả năng rất tốt và có thể được sử dụng như trong môi trường của bạn.
Đối với nhiều thứ đơn giản trong môi trường ES5, sử dụng Object hoạt động rất tốt. Nếu objlà đối tượng của bạn và Alà một biến có giá trị bạn muốn thao tác trong tập hợp, thì bạn có thể thực hiện các thao tác sau:
Mã khởi tạo:
// 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};
Câu 1: Có Atrong danh sách:
if (A in obj) {
// put code here
}
Câu hỏi 2: Xóa 'A' khỏi danh sách nếu có:
delete obj[A];
Câu hỏi 3: Thêm 'A' vào danh sách nếu nó chưa có
obj[A] = true;
Để đầy đủ, thử nghiệm cho dù Atrong danh sách có an toàn hơn một chút với điều này:
if (Object.prototype.hasOwnProperty.call(obj, A))
// put code here
}
do xung đột tiềm ẩn giữa các phương thức tích hợp và / hoặc các thuộc tính trên Đối tượng cơ sở như thuộc constructortính.
Thanh bên trên ES6: Phiên bản làm việc hiện tại của ECMAScript 6 hoặc đôi khi được gọi là ES 2015 có đối tượng Set tích hợp . Nó được thực hiện ngay bây giờ trong một số trình duyệt. Vì tính khả dụng của trình duyệt thay đổi theo thời gian, bạn có thể nhìn vào dòng Settrong bảng tương thích ES6 này để xem trạng thái hiện tại cho tính khả dụng của trình duyệt.
Một lợi thế của đối tượng Set tích hợp là nó không ép buộc tất cả các khóa vào một chuỗi như Object làm để bạn có thể có cả 5 và "5" làm các khóa riêng biệt. Và, bạn thậm chí có thể sử dụng Đối tượng trực tiếp trong tập hợp mà không cần chuyển đổi chuỗi. Đây là một bài viết mô tả một số khả năng và tài liệu của MDN về đối tượng Set.
Bây giờ tôi đã viết một polyfill cho đối tượng thiết lập ES6 để bạn có thể bắt đầu sử dụng ngay bây giờ và nó sẽ tự động chuyển sang đối tượng thiết lập sẵn nếu trình duyệt hỗ trợ. Điều này có lợi thế là bạn đang viết mã tương thích ES6 sẽ hoạt động hoàn toàn trở lại IE7. Nhưng, có một số nhược điểm. Giao diện thiết lập ES6 tận dụng các trình lặp ES6 để bạn có thể thực hiện những việc như thế for (item of mySet)và nó sẽ tự động lặp lại thông qua bộ cho bạn. Nhưng, loại tính năng ngôn ngữ này không thể được thực hiện thông qua polyfill. Bạn vẫn có thể lặp lại một bộ ES6 mà không cần sử dụng các tính năng ngôn ngữ ES6 mới, nhưng thật lòng mà không có các tính năng ngôn ngữ mới, nó không tiện lợi như giao diện thiết lập khác mà tôi đưa vào bên dưới.
Bạn có thể quyết định cái nào phù hợp nhất với bạn sau khi nhìn vào cả hai. Bộ polyfill ES6 có tại đây: https://github.com/jfriend00/ES6-set .
FYI, trong thử nghiệm của riêng tôi, tôi đã nhận thấy rằng việc triển khai Firefox v29 Set không được cập nhật đầy đủ trên bản nháp hiện tại của thông số kỹ thuật. Ví dụ: bạn không thể thực hiện các .add()cuộc gọi phương thức như thông số kỹ thuật mô tả và hỗ trợ polyfill của tôi. Đây có lẽ là một vấn đề của một đặc điểm kỹ thuật trong chuyển động vì nó chưa được hoàn thiện.
Các đối tượng được thiết lập sẵn: Nếu bạn muốn một đối tượng đã được xây dựng có các phương thức để vận hành trên một tập hợp mà bạn có thể sử dụng trong bất kỳ trình duyệt nào, bạn có thể sử dụng một loạt các đối tượng dựng sẵn khác nhau thực hiện các loại tập hợp khác nhau. Có một miniset là một mã nhỏ thực hiện những điều cơ bản của một đối tượng được thiết lập. Nó cũng có một đối tượng tập hợp nhiều tính năng hơn và một số dẫn xuất bao gồm Từ điển (cho phép bạn lưu trữ / truy xuất giá trị cho mỗi khóa) và Đối tượng (cho phép bạn giữ một tập hợp các đối tượng - đối tượng JS hoặc đối tượng DOM nơi bạn cung cấp hàm tạo một khóa duy nhất cho mỗi một hoặc Objectset sẽ tạo khóa cho bạn).
Đây là bản sao mã cho miniset (mã cập nhật nhất có ở đây trên 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;