JS关于数组的相关操作讲解与对比

168 阅读11分钟
    在js中对数组的操作函数有很多,在这里只对其中比较常用的方法做一下简单的说明的对比。 既然说到对比,我们首先对这些函数分为两大类进行一下对比。 一种是可以改变原数组的函数,另一种则是不会改变原数组--返回新数组--的方法了。


一 数组分类 

一  可以改变原数组的方法

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()
  • flat()

二  不会改变原数组的方法---返回新的数组

  • filter()
  • concat()
  • slice()
  • join()
目前脑海中就这些函数了,后续想起来会陆续补充。大家要是发现了可以在评论区告诉我,我会尽快补充上。


二  函数解释与对比

##push()

首先介绍push()函数,我想大家可能已经对这个方法很了解了。

这个方法是数组的末尾加入一个或者多个元素,并返回新的数组的长度

举个例子:

var aaa = ["1", "2", "3", "4", "5", "6", "7"];
aaa.push("a");
console.log(aaa)

我们定义好一个名为aaa的数组  然后用push方法增加一个元素“a”,我们会发现他返回了数值8,而8刚好是新的数组的长度,我们再次在控制台输出aaa发现数组的末尾添加了一个元素a。


当让我们也可以一次性的添加多个元素,比如aaa.push("a","b","c","d")

##pop()

pop()函数的作用是去掉数组末尾的一个元素,并返回被删除的那个数组元素。当我们对数组aaa执行

aaa.pop();

的时候,输出结果以及原数组的情况如下图所示,返回值为被删除的元素。



##shift()

shift()函数的作用是删除掉数组起始位置的元素,并返回被删除的数组元素。同理,执行

aaa.shift()

的时候,输出结果以及原数组的情况如下图所示,返回值为被删除的元素。



##unshift()

unshift()函数的作用和push()的用法类似,但是unshift()的作用是在数组的起始位置添加一个或者多个新的元素。返回新的数组长度。依旧以aaa数组为例,当我们执行

aaa.unshift("First");

的时候,结果如下,原数组变化情况如下。


当然,我们也可以像push()的用法一样,一次性的插入多个元素

aaa.unshift("123","Second");


##splice()

splice()函数的作用相对灵活一些,方法通过删除替换现有元素或者原地添加新的元素来修改数组。并以数组形式返回被修改的内容。

首先看一下他的语法(大家也可以移步MDN官方文档来查看详解)

array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

start参数:指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于array.length-n);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。

上面是官方文档里面的说法,可能听起来比较绕,但是大体总结起来就是正常从0开始算,负数从后往前数。

deleteCount参数:可选。

  deleteCount 为整数,表示要移除的数组个数。

  deleteCount被省略,那么start之后的数组全被删除。

  deleteCount为0或者负数,不移除,并且从start位置添加一个新元素。

item1.....参数:可选  要添加的元素。

看到这splice()函数的描述文字最多。而且当你状态不好迷迷糊糊的时候不容易看进去?看进去了是不是不容易记住?没关系,我们练一遍就好了。别信广告,信疗效!

我们随便定义一个数组,暂且叫他。。没错。。还是aaa,然后我们输入以下代码

aaa.splice(1,2);
console.log(aaa);

这段代码的意思就是,aaa数组,从0开始数,从1开始删除2个元素。如下图所示,aaa数组共8个元素,从索引为1开始删除2个,返回值为["2","3"]--这就是以数组形式返回被删除的数组--原数组aaa长度变为2。这是对于数组的删除操作。


例子2,没错,继续是aaa数组,我们打开控制台输入以下代码对其操作,看看效果。

aaa.splice(1,0,"child1","child2");
console.log(aaa);

这段代码的意思aaa数组从第一位开始删除0个,添加child1和child2元素。

由于是删除0个元素,所以返回结果为一个空数组。这是对数组的添加操作。


例子3,继续对aaa数组进行如下操作

aaa.splice(0,3,"parent1","parent2");

这段代码的意思是aaa数组从第0位开始删除3个元素,并添加parent1和parent2两个元素。这就相当于将2个元素进行了替换操作。


基于以上,我们再继续列举几种情况。

aaa.splice(-2,2);

将aaa数组从末位第二个开始删除2个。当然,虽然start对应的参数是-2,但这只意味着从末位第几位开始,所有计数都要从前往后数的。。。。。。


aaa.splice(2);

将aaa数组从第二位开始以后的全部都删除掉。


好,对于aaa数组的折腾暂时就到这。splice()函数灵活多变,需要活学活用。

##sort()

用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的。

以上是官方文档的解释,它里面强调了一句话先将元素抓华为字符串,然后再进行比较。这句话啥意思呢?我们先来举个例子。

var array1 = ["1","2","10000","9999","4","3","8","901","10"];
array1.sort();

可能我们原来想的结果,亦或者按照数值的从小到大,亦或者按照从大到小。但是,结果总是残酷的。


如上图,经过排序的array1数组变成了["1", "10", "10000", "2", "3", "4", "8", "901", "9999"] 这样的一个数组。虽然与我们现象的不一样,但是冥冥之中貌似也有一种规律可循似的。那我们怎样才能得到我们自己想要的排序呢?我们先看以下sort()的语法:

arr.sort([compareFunction])

compareFunction参数:用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。(后面这句话就解释了冥冥之中的规律就是这个)

他居然可以是一个函数!!!那就好了,那就意味着,我想怎么样让他排序,他就得怎么给我排序!

首先,我想让你按照数值的从大到小进行排列

array1.sort((a,b) => b-a)

利用以上代码,array1数组的结果就变成了 ["10000", "9999", "901", "10", "8", "4", "3", "2", "1"]

那要是是从小到大呢????我不会,你自己想--手动苦瓜脸~~~总之你可以根据你自己的需求想怎么排序就怎么排序。


##reverse()

这个方法比较简单,颠倒数组中元素的位置,改变了数组,并返回新数组。就是头变尾,尾变头。

简单来说呢,就是

var a = ["1","2","3"];
console.log(a);
a.reverse();
console.log(a);

第一个输出的结果是["1", "2", "3"],第二个输出结果是["3", "2", "1"]。结果显而易见。

官方晚上给出了一个很好的例子,可以延申学习一下。我们首先定义一个类数组bbb它包含三个元素和一个length属性。

var bbb =  {0: 1, 1: 2, 2: 3, length: 3}

如果我想调转bbb的话,直接使用reverse()是不可以的。需要做一下小操作。

Array.prototype.reverse.call(bbb);

这样就可以调换bbb了,调换结果如下:

{0: 3, 1: 2, 2: 1, length: 3}

关于call方法和相关的apply方法网上有很多详细解释,我再这里就不再多说了,大家可以自行百度以下。


##flat()

方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回

如果您没明白上面这段话啥意思,咱们直接上代码。

var arr1 = [1, 2, [3, 4]];
arr1.flat(); 
// [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

任你任意深度我都可以给你扁平化,此方法何以灵活的和call和apply搭配使用。

小结

至此我们把可以改变数组4的方法都简单的介绍了一下,他们有的方法可以相互替代,这个就需要具体根据实际情况去使用了。关于他们的返回值需要注意一下,有的是返回新的数组,而有的则是返回数组长度以及被操作的数组元素。

那么这里我们再引申一个问题,假设有这么一种情况

我先定义了一个数组aaa然后我们定义一个数组bbb让他等于aaa,这个时候我们操作aaa数组的话,bbb会跟着变化吗?

var aaa = ["a","b","c"];
var bbb = aaa;
aaa.pop();
console.log(aaa);
console.log(bbb);

经过试验我们会发现,其实修改其中任何一个另一个都会跟着变化。这是因为JS中Array是引用类型,也就是说aaa和bbb他们的原始数据存储的地址是一致的,所以修改了数据之后,他们都会跟着变。那么如果我希望修改数据并且不改变原来数组要怎么办呢?这个时候不改变原数组的函数就可以闪亮登场了。


##filter()

filter()是创建了一个新的数组,其包含所提供的函数预测的所有元素。

从上面的意思上看,他会创建一个新的数组不改变原有的数组。我们可以创建一个函数来再数组中提取中我们需要的元素。知道了这两个信息,我们就可以做一个简单的例子。

var array2 = ["1","2","3","4","5","6","7","8"];
var array3 = array2.filter(item => item >5);
console.log(array2);
console.log(array3);

第一个输出结果依旧是原数组没有改变:["1", "2", "3", "4", "5", "6", "7", "8"]

第二个输出结果变成了数组中大于5的元素:["6", "7", "8"]

这样就可以验证了我们以上说的那些信息。

我这里面只是举了一个简单的例子,我们可以自行根据实际情况写一个过滤数据的方法,然后利用这种形式 --某数组.filter(自己写的function)-- 来实现过滤,查找等操作。


##concat()

方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组

根据字面意思我们就可以知道他的用途,直接上代码加深一遍印象!

var num1 = [1, 2, 3],  
var num2 = [4, 5, 6],  
var num3 = [7, 8, 9];  
var nums = num1.concat(num2, num3);
console.log(nums);  
// results in [1, 2, 3, 4, 5, 6, 7, 8, 9]


##slice()

 方法返回一个新的数组对象,这一对象是一个由 beginend 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变

begin:提取起始处的索引(从 0 开始),从该索引开始提取原数组元素。

end:提取终止处的索引(从 0 开始),在该索引处结束提取原数组元素。

二者结尾可选参数,非必选。

这个方法貌似和splice()很像,但又有很多不同。直接上代码看结果

const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];

console.log(animals.slice(2));
// expected output: Array ["camel", "duck", "elephant"]

console.log(animals.slice(2, 4));
// expected output: Array ["camel", "duck"]

console.log(animals.slice(1, 5));
// expected output: Array ["bison", "camel", "duck", "elephant"]

看到结果大家就应该明白了。而且slice()不改变原数组!


##join()

方法将一个数组的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。

join()的语法只有一个参数,这个参数就是我们指定的字符串来作为分隔符。

老规矩,直接撸代码。

const elements = ['Fire', 'Air', 'Water'];

console.log(elements.join());
// expected output: "Fire,Air,Water" 默认分隔符是逗号

console.log(elements.join(''));
// expected output: "FireAirWater"

console.log(elements.join('-'));
// expected output: "Fire-Air-Water"


const element1 = ['Fire'];
console.log(element1.join('-'))
//expected output: "Fire"

const element2 = []
console.log(element2.join('-'))
//expected output: 空字符串


三 总结

其实关于JS的数组操作的方法还有很多,这里就不一一列举了。给大家一个传送门,以后可以当作一个工具文档来随时查阅。