在我最近的一篇名为《 为ECMAScript 6做准备:Map和WeakMap》中的文章中 ,我向您介绍了ECMAScript 6中可用的两种新数据类型: Map
及其弱类WeakMap
。 在本教程中,我们将介绍另一个类似的数据类型,称为Set
和WeakSet
。 它们与Map
和WeakMap
有很多相似之处,尤其是在可用方法方面。 但是,正如我们将在此处讨论的那样,它们具有不同的范围。
正如我在前面所有讨论ECMAScript 6的文章中所指出的那样,如果您想填充我们要介绍的内容,则可以使用Paul Miller的 es6-shim 。
Set
顾名思义, Set
数据类型表示一组元素(一个集合)。 正如数学概念所暗示的,这意味着一个集合只允许您将相同的元素存储一次(例如,字符串“ test”不能存储两次)。 与其他JavaScript数据类型一样,存储相同类型的元素不是强制性的,因此在同一集合中可以存储数组,数字,字符串等。
还值得注意的是,例如使用get()
方法无法检索集合中的单个元素。 原因是元素既没有键也没有索引,您可以引用该索引来检索它。 但是因为可以验证元素是否包含在给定的Set
实例中,所以不需要get()
方法。 例如,如果您知道字符串“ test”包含在集合中,则无需检索它,因为您已经具有该值。 正如您将在本教程中了解的那样,仍然可以检索所有存储的元素。
“但是什么时候适合这种数据类型?” 你可能会问。 好吧,假设您需要存储某些元素的ID。 在这些情况下,您不希望重复。 在这种情况下,在ECMAScript 5中,大多数人可能已经使用数组或对象来存储元素。 问题在于,每次引入新元素时,都必须检查是否尚未添加该元素,以避免重复。 如果使用数组,则将具有以下代码:
var collection = [1, 2, 3, 4, 5];
var newElements = [4, 8, 10];
for(var i = 0; i < newElements.length; i++) {
if (collection.indexOf(newElements[i]) === -1) {
collection.push(newElements[i]);
}
}
使用Set
数据类型,可以简化前面的代码,如下所示:
var collection = new Set([1, 2, 3, 4, 5]);
var newElements = [4, 8, 10];
for(var i = 0; i < newElements.length; i++) {
collection.add(newElements[i]);
}
现在您知道Set
是什么,以及何时使用它,让我们讨论所公开的属性和方法。
Set.prototype.size
size
属性返回Set
实例中的元素数。 这类似于Array
数据类型的length
。
Set.prototype.constructor()
您可能知道,该构造函数用于实例化新对象。 它接受一个称为iterable
的可选参数,它是一个数组或可迭代对象,其元素将添加到新集中。 使用的基本示例如下所示:
var array = [1, 2, "test", {a: 10}];
var set = new Set(array);
Set.prototype.add()
如果尚不存在,则add()
方法将新元素添加到集合中。 否则不会添加该元素。 此方法的签名如下:
Set.prototype.add(value)
其中value
是要存储的元素。 此方法修改了它所调用的集合,但还返回了新集合,允许链接。 下面显示了如何使用此功能的示例:
var set = new Set();
set.add("test").add(1).add({});
目前,此方法已在Firefox,Internet Explorer 11,Chrome 38和Opera 25中实现。在38之前的Chrome版本和25之前的Opera中,在激活“启用实验性JavaScript”标志之后,支持此方法。
Set.prototype.delete()
以相同的方式,我们可以添加元素,也可以从集合中删除它们。 为此,我们可以使用delete()
方法。 它接受要删除的值,如果成功删除了该元素,则返回true
否则返回false
。 该方法的签名如下所示:
Set.prototype.delete(value)
value
表示要删除的元素。
目前,此方法已在Firefox,Internet Explorer 11,Chrome 38和Opera 25中实现。在38之前的Chrome版本和25之前的Opera中,您必须激活通常的标记。
Set.prototype.has()
has()
方法是Set
数据类型与Map
共同的方法之一。 它允许我们验证元素是否存在于集合中。 如果找到该值,则返回true
否则返回false
。 此方法的签名如下:
Set.prototype.has(value)
其中value
是您要搜索的值。
目前,此方法已在Firefox,Internet Explorer 11,Chrome 38和Opera 25中实现。在38之前的Chrome版本和25之前的Opera中,在激活“启用实验性JavaScript”标志之后,支持此方法。
Set.prototype.clear()
与在Map
定义的方法一样, clear()
方法是从Set
实例中删除所有元素的便捷方法。 该方法没有返回值(这意味着它返回undefined
)。 clear()
的签名如下所示:
Set.prototype.clear()
clear()
当前在Firefox,Internet Explorer 11,Chrome 38和Opera 25中实现。在38之前的Chrome版本和25之前的Opera中,您必须激活通常的标志。
Set.prototype.forEach()
与Map
相同的另一种方法是forEach()
。 我们可以使用它来按插入顺序遍历存储在集合中的元素。 forEach()
的签名如下:
Set.prototype.forEach(callback[, thisArg])
callback
是在集合中的每个元素上运行的函数。 thisArg
参数用于设置回调的上下文( this
)。 callback
接收三个参数:
-
value
:处理的元素的值 -
value
:处理的元素的值 -
set
:处理Set
对象
如您所见,正在处理的值传递了两次。 原因是使该方法与Map
和Array
实现的forEach()
保持一致。
Firefox,Internet Explorer 11,Chrome 38和Opera 25支持此方法。在38之前的Chrome和25之前的Opera的版本中,您必须激活通常的标志。
Set.prototype.entries()
entries()
方法使我们能够获得一个Iterator
以遍历集合的元素。 Iterator
按插入顺序包含value
数组-集合中每个元素的value
对。 重复的原因与之前相同:使其与Map
的方法保持一致。 此方法的签名是:
Set.prototype.entries()
Firefox,Chrome 38和Opera 25当前支持此方法。在38之前的Chrome版本和25之前的Opera中,您必须激活通常的标记。
Set.prototype.values()
属于此数据类型的另一种方法是values()
。 它按插入顺序返回一个Iterator
对象,该对象包含集合中元素的值。 其签名如下:
Set.prototype.values()
Firefox,Chrome 38和Opera 25当前支持此方法。在38之前的Chrome版本和25之前的Opera的版本中,在激活“启用实验性JavaScript”标志之后支持此方法。
Set.prototype.keys()
奇怪的是, Set
还有一个keys()
方法。 它执行与values()
相同的操作,因此我将不对其进行描述。
WeakSet
WeakSet
是Set
数据类型的弱项。 WeakSet
仅接受对象作为其值。 这意味着允许{}
, function(){}
(函数继承自Object
)和您自己的类的实例,但不允许使用"test"
, 1
和其他原始数据类型。
另一个重要的区别是,如果没有其他对对象的引用存储,则WeakSet
对象不会阻止垃圾回收(该引用是weak )。 由于存在这种差异,因此没有任何一种方法可以一次检索值或一个以上的元素,例如Set.prototype.values()
和Set.prototype.entries()
。 另外,类似于WeakMap
,没有size
属性可用。
最后一点,我想强调一点,Chrome 37和Opera 24支持WeakSet
及其方法,但不带标志,而Set
并非如此。 默认情况下,较新版本的Chrome 38和Opera 25支持Set
及其方法。
全部放在一起
现在您已经了解了Set
和WeakSet
数据类型的所有方法和属性,是时候将它们付诸实践了。 在本节中,我开发了两个演示,以便您可以使用这些方法并更好地了解它们的功能。 正如您将注意到的,我没有使用Set.prototype.keys()
方法,因为我认为它仅能使开发人员感到困惑。
在第一个演示中,我将使用Set
对象及其方法( Set.prototype.keys()
除外Set.prototype.keys()
。
// Creates a new Set object
var set = new Set();
// Defines an array will be stored in the set
var arr = [4, 1, 9];
// Adds a new Number to the set
set.add(1);
// Adds a new String to the set
set.add('Aurelio De Rosa');
// Adds a new Object to the set
set.add({name: 'John Doe'});
// Adds a new Array element to the set
set.add(arr);
// Checks whether the string "test" is stored in the set. Prints "false"
console.log(set.has('test'));
// Checks whether the number "1" is stored in the set. Prints "true"
console.log(set.has(1));
// Retrieves the set size. Prints "4"
console.log(set.size);
// Deletes the object {name: 'Aurelio De Rosa'}. Prints "false" because even if it has the same values and properties, it's a different object
console.log(set.delete({name: 'Aurelio De Rosa'}));
// Retrieves the set size. Prints "4"
console.log(set.size);
// Deletes the array arr. Prints "true" because it's the same array
console.log(set.delete(arr));
// Retrieves the set size. Prints "3"
console.log(set.size);
// Loops over each element of the set
set.forEach(function(value, samevalue, set) {
// Prints the value twice
console.log('Value ' + value + ' is the same as ' + samevalue);
});
var entries = set.entries();
var entry = entries.next();
// Loops over each element of the set
while(!entry.done) {
// Prints both the value and the key
console.log('Value ' + entry.value[1] + ' is the same as ' + entry.value[0]);
entry = entries.next();
}
var values = set.values();
var value = values.next();
// Loops over each value of the set
while(!value.done) {
// Prints the value
console.log('Value: ' + value.value);
value = values.next();
}
// Deletes all the elements in the set
set.clear();
// Retrieves the set size. Prints "0"
console.log(set.size);
下面显示了先前代码的实时演示,并且还可以作为JSFiddle获得 。
在第二个演示中,我们将看到如何使用WeakSet
对象。
// Creates a new WeakSet object
var weakset = new WeakSet();
// Defines an object that will be stored in the set
var obj = {name: 'Aurelio De Rosa'};
// Adds an object to the set
weakset.add(obj);
// Adds a function to the set
weakset.add(function(){});
// Adds another object to the set
weakset.add({name: 'John Doe'});
// Checks whether the Object {name: 'John Doe'} exists in the weak set. Prints "false" because despite the fact that the passed object and the stored one have the same values and properties, they are different objects
console.log(weakset.has({name: 'John Doe'}));
// Checks whether the Object obj exists in the weak set. Prints "true" because it's the same object
console.log(weakset.has(obj));
// Deletes the obj element. Prints "true"
console.log(weakset.delete(obj));
// Deletes the function(){} element. Prints "false" because the passed function and the stored one they are different functions (objects)
console.log(weakset.delete(function(){}));
// Deletes all the elements of the weak set
weakset.clear();
下面显示了先前代码的实时演示,并且还可以作为JSFiddle获得 。
结论
在本教程中,我介绍了新的Set
和WeakSet
数据类型。 除了Map
和WeakMap
之外,它们还是ECMAScript 6中可用的最有趣的新类型。希望您喜欢本文并学到一些有趣的东西。
From: https://www.sitepoint.com/preparing-ecmascript-6-set-weakset/