每个使用JavaScript编程的人都应该对Array很是熟悉。 一般,咱们能够这样形容它:数组是表示一种储存在连续空间中的结构类型(内容能够为number,object等)。 例如:[1, 2, 3, 4, 5]
(原文这里说法存在歧义,具体数组在内存中的存储方式能够参考连接一、连接二)javascript
而Set更像是一种抽象的数据类型。它只包含不一样的元素/对象,不须要连续分配存储空间。 例如:{1, 2, 3}
java
它们之间最大的差异就是Array中的元素是能够重复的,而Set中的元素不可重复 。除此以外,Array被认为是一种索引集合,而Set是一种键的集合。es6
索引集合是指按下标做为索引值排序的数据结构
键的集合使用key访问元素,访问顺序与元素插入顺序一致。编程
很简单对吧?如今可能有人会问,既然这二者如此不一样,为何还要将它们进行比较?数组
在编程时,咱们可使用Array或Set来存储相同的数据集。但根据使用状况,咱们应该选用正确的数据结构以助于提供最佳的解决方案。为了实现这个目标,首先咱们须要了解它们分别是什么,有什么特色和能力。前面的文章中咱们对这两种数据结构已经有了初步的了解,接下来就来看看它们的构建方式。浏览器
数组的构建很是简单直接,在JS中声明一个数组你能够直接使用字面上的语法:数据结构
var arr = []; //空数组
var arr = [1,2,3]; //元素为1,2,3的数组
复制代码
或者使用构造函数:函数
var arr = new Array(); //空数组
var arr = new Array(1,2,3);//元素为1,2,3的数组
复制代码
甚至这种更酷的方法:性能
var arr = Array.from("123"); //["1","2","3"]
复制代码
注: 一条建议——除了非用不可的状况尽可能不要使用new Array()
,缘由以下:ui
new Array()
的性能比[]
慢不少[]
节约更多输入的时间var arr1 = new Array(10); //长度为10,每一个元素都为undefined
var arr2 = [10]; // arr2[0] = 10 且 arr2.length = 1;
var arr3 = new Array(1,2,3); //[1,2,3]
var arr4 = [1,2,3];//[1,2,3]
复制代码
因此,尽可能保持一个原则——简单化
Set使用内置的构造函数初始化,没有其它简便的方法。
Set([iterable])
想要建立一个Set
,须要使用new
方法,例如:
var emptySet = new Set();
var exampleSet = new Set([1,2,3]);
复制代码
不能使用以下方式:
new Set(1);
复制代码
Set接收一个可遍历的对象做为其输入参数,并将遍历元素依次做为Set中的元素生成对象。所以,咱们能够经过数组做为参数去建立Set——但建立的Set中只包含数组中的非重复元素,如上文提到,Set中元素不可重复。
固然,咱们也能经过Array.from()
方法将Set还原为数组:
var set = new Set([1,2,3]); // {1,2,3}
var arr = Array.from(set);//[1,2,3]
复制代码
如今,咱们知道了如何构建这两种数据结构,接下来让咱们对Array / Set提供的最基本方法进行比较。
console.log(set[0]); //undefined
console.log(arr[0]); //1
复制代码
Set.prototype.has(value)
。Array:Array.prototype.indexOf(value)
。console.log(set.has(0)); // boolean - false
console.log(arr.indexOf(0)); // -1
console.log(set.has(1)); //true
console.log(arr.indexOf(1)); //0
复制代码
这意味着在Array中,咱们须要额外建立检查元素是否在Array中的条件:
var isExist = arr.indexOf(1) !== -1;
复制代码
注:ES6提供了与Set.prototype.has()
类似的方法Array.prototype.includes()
来判断元素是否在数组中,但这个方法并无普遍地被浏览器支持——好比IE..
Array.prototype.push()
方法快速完成——元素将会被插入到数组的末尾。arr.push(4); //[1,2,3,4]
复制代码
Array.prototype.unshift()
方法实现——元素被插入到数组的头部。arr.unshift(3); //[3,1,2,3]
arr.unshift(5, 6); //[5,6,3,1,2,3]
复制代码
Set.prototype.add()
。因为Set须要保持其“元素不可重复”的特性,因此每次调用add()
方法,Set都须要便利全部元素以确保无重复元素,一般状况下add()
方法的时间复杂度应为O(n)。不过Set的内部采用哈希表的实现方式,所以能够达到O(1)的时间复杂度。set.add(3); //{1,2,3}
set.add(4); //{1,2,3,4}
复制代码
var arr = [5, 6, 1, 2, 3, 4]
复制代码
pop()
——删除并返回最后一个元素,时间复杂度O(1)
arr.pop();//return 4, [5,6,1,2,3]
复制代码
shift()
——删除并返回第一个元素,时间复杂度O(n)
arr.shift(); //return 5; [6,1,2,3]
复制代码
splice(index, delectCount)
——删除从index开始的delectCount个元素。时间复杂度为O(n)
arr.splice(0,1); //[1,2,3]
复制代码
var set = new Set([1, 2, 3, 4]);
复制代码
delete(element)
——删除指定的element
set.delete(4); //{1,2,3}
复制代码
clear()
——清空Set中全部元素
set.clear(); //{}
复制代码
Array并未提供原生方法删除指定元素,咱们须要借助其它方法找到元素对应下标,经过splice()
删除,而Set能够直接使用delete()
进行删除。
另外,对比Set只提供了一些基本的操做数据的方法,Array提供了更多实用的原生方法(reduce()
,map()
,sort()
等),因此有些人可能会想,为何咱们比起Array会更喜欢Set?
delete()
方法,使求两个Set的交/并集的操做比求两个数组的交/并集的操做更简单。总之,就我而言对比Array,Set并无明显优点,除了在特定场景中,例如当咱们想要以最小成本维护不重复的数据,或者使用到大量不一样的数据集时只须要使用最基本的集合操做而无需直接访问元素。
不然,Array一般是更好的选择。由于在须要时获取元素更节省CPU工做量。
欢迎讨论。
其余资料连接: