认识JS的Array类型
ECMAScript数组的每一项可以保存任何类型的数据,并且数组的大小是可以动态调整的。
创建数组的基本方式有两种,分别是
- 使用Array构造函数
我们可以给构造函数传递数组长度,或者数组的内容。
1 | var people = new Array() |
当你给构造函数传值时,可以不用new操作符
1 | var nums = Array(3) |
- 使用数组字面量表示法。
数组字面量由一对包含数组项的方括号表示,多个数组项以逗号隔开。
1 | var colors = ['red', 'blue', 'yellow'] |
在读取和设置数组的值时,要使用方括号并提供相应的索引值(从0开始)
1 | var colors = ['red', 'blue', 'yellow'] |
数组的length属性很有特点,它不是只读的,你可以从数组移项,也可以往数组添加项,如下
1 | var colors = ['red', 'blue', 'yellow'] |
数组的长度等于最后一项的索引加一
1 | var colors = ['red', 'blue', 'yellow'] |
检测数组
可以使用instanceof判断某个对象是不是数组
1 | if (value instanceof Array) { |
但是它只假定只有一个全局环境,如果遇到两个全局环境就不适用了,什么时候会有多个全局环境呢,就是网页中有多个框架的时候。
因此有一个更好的方法检测数组,就是Array.isArray()
1 | if (Array.isArray(value)) { |
转换方法
所有对象都有,每次所有对象都有toLocaleString(), toString(), valueOf()方法。数组调用valueOf返回的还是数组本身;而调用数组的toString()会去调用每一项的toString()方法然后拼接成一个以逗号分隔的字符串,同理,toLocaleString()也是如此。
1 | var colors = ['red', 'blue', 'green'] |
以上三种方法默认情况下都是以逗号分隔项
如果你使用join就可以用不同的分隔符来构建这个字符串,如下
1 | var colors = ['red', 'blue', 'green'] |
栈方法
栈是一种LIFO(last in first out,后进先出)的数据结构,也就是最新添加的项最早被移除,它可以限制插入和删除项。
数组的push和pop方法就表现得跟栈类似。
- push():可以接受任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度,注意是返回数组长度。
- pop(): 从数组末尾移除最后一项,减少数组的length,然后返回移除的项,注意返回的是移除的项。
1 | var colors = ['red', 'blue'] |
队列方法
队列是一种FIFO的数据结构(先进先出),前面栈是后进先出。队列在列表的末端添加项,从列表的前端删除项。
这里介绍一种删除数组项的方法shift(),它能够删除数组中的第一项并返回该项,同时将数组长度减一,注意返回的是删除项!
要像使用队列一样使用数组,实现方法就是shift()+push()
1 |
|
这里再介绍一个方法unshift(), 顾名思义,unshift()与shift()的用途相反,它是在数组前端添加任意个项并返回数组的长度。
如果想从相反方向模拟队列,就是unshift()+pop()
1 | var colors = new Array() |
重排序方法
reverse()和sort()
reverse():就是反转数组项的顺序
1
2
3var arr = [1,2,3,4,5]
arr.reverse()
console.log(arr) // [ 5, 4, 3, 2, 1 ]sort():按照升序(从小到大)给数组项排序
sort()比较的是字符串(数组项转为字符串),也就是说如果直接用它,数组项为数值的排序结果并不理想1
2
3var arr = [0,1,5,10,15]
arr.sort()
console.log(arr) // [ 0, 1, 10, 15, 5 ]
因此,sort()方法可以接收一个比较函数作为参数,这个比较函数接收两个参数。(面试题经常出现这种比大小的题)
1 | function compare(v1,v2){ |
操作方法
- concat():基于当前数组中的所有项创建一个新数组,不改变原数组
具体来说就是,先创建当前数组的一个副本,然后将接收到的参数添加在数组末尾。
- 不给concat()方法传递参数,它只是返回创建的副本。
- 给concat()方法传递一个或者多个数组,它会将数组中的每一项添加到创建的数组副本中。
- 给concat()方法传递非数组的值,它会把这些值直接添加到数组末尾。
1
2
3
4var colors = ['red', 'green', 'blue']
var colors2 = colors.concat('pink', ['black', 'yellow'])
console.log(colors) // [ 'red', 'green', 'blue' ]
console.log(colors2) // [ 'red', 'green', 'blue', 'pink', 'black', 'yellow' ]
- slice():基于当前数组的一个或多个项创建一个新数组,不改变原数组
slice()方法可以接收一个或者两个参数,即要返回的项的起始和结束位置(不包括结束位置的项)
- 只接收一个参数,则返回从该参数指定位置的项到当前数组末尾的所有项。
- 接收两个参数,则返回起始和结束位置之间的项(包括起始位置的项,但不包括结束位置的项)
1
2
3
4
5
6var colors = [ 'red', 'green', 'blue', 'pink', 'black', 'yellow' ]
var colors2 = colors.slice(1)
console.log(colors2) // [ 'green', 'blue', 'pink', 'black', 'yellow' ]
var colors3 = colors.slice(2,4)
console.log(colors3) // [ 'blue', 'pink' ]
console.log(colors) // [ 'red', 'green', 'blue', 'pink', 'black', 'yellow' ]
如果slice接收的参数是负数,则用数组长度加上该数来确定相应的位置。如在一个长度为5的数组调用slice(-2, -1), 等于slice(3, 4)。如果结束位置小于起始位置,则返回空数组。
- splice():主要用途是向数组中部插入项,会改变原数组。
- 删除:可以指定2个参数(要删除的第一项的位置和要删除的项数),然后删除任意数量的项。
1
2
3
4var colors = ['red', 'green', 'blue', 'yellow']
var colors1 = colors.splice(1,2)
console.log(colors) // [ 'red', 'yellow' ]
console.log(colors1) // [ 'green', 'blue' ]
从上面例子可以看出,splice()方法返回的是删除的项所组成的数组,如果没有删除的项,则返回空数组,下面例子可见。
- 插入&替换:输入三个参数(起始位置,要删除的项数,要插入的项),如果插入多个项,可以有第四、第五个参数;如果要删除的项为0,那就是插入作用;如果不为0那就是替换。
1 | var colors = ['red', 'green', 'blue', 'yellow'] |
位置方法
indexOf()和lastIndexOf(),都接收一个或两个参数(分别是要查找的项和查找的起始位置的索引),indexOf从数组开头的位置(默认0)开始向后查找,lastIndexOf从数组结尾的位置(默认length-1)开始向前查找。
这两个方法都返回要查找的项在数组中的位置,在没有找到的情况下返回-1;它在查找的时候是使用全等操作符(===),也就是查找的项必须严格相等。
1 | var nums = [1, 2, 3, 4, 5, 4, 3, 2, 1] |
迭代方法
数组的5种迭代方法,每个方法接收两个参数,分别是要在每一项上运行的函数以及运行该函数的作用域对象——影响this的值。要在每一项上运行的函数接收三个参数,分别是数组项的值,该项在数组中的位置,以及该数组本身。
以下是这5种方法:
- every():若数组所有项都使得运行函数返回true(即每一项都满足运行函数的要求),则返回true。
- some():若数组中只要有一项使得运行函数返回true(有一项满足运行函数的要求),则返回true。
- filter():返回查询数组中符合某些条件的所有数组项。
- map():返回包含的项跟数组一一对应的数组。
- forEach():相对于for循环,对数组每一项进行操作,没有返回值。
every()
1 | var nums = [1, 2, 3, 4, 5, 4, 3, 2, 1] |
一旦发现不符合要求的,立马返回false,不去校验剩余的每一项
some()
1 | var nums = [1, 2, 3, 4, 5, 4, 3, 2, 1] |
一旦发现符合要求的,立马返回true,不去校验剩余的每一项
filter()
1 | var nums = [1, 2, 3, 4, 5, 4, 3, 2, 1] |
map()
1 | var nums = [1, 2, 3, 4, 5, 4, 3, 2, 1] |
forEach()
1 | var nums = [1, 2, 3, 4, 5, 4, 3, 2, 1] |
三个参数不一定都要传,但至少要操作的数组项要传。
归并方法
reduce()和reduceRight()这两个方法会迭代数组所有项,然后构建最终返回的值。
reduce()方法从数组第一项开始遍历到最后,reduceRight()从数组最后一项开始遍历到最前面。
两个方法都接收两个参数:在每一项上执行的函数以及(可选的)作为归并基础的初始值。
在每一项上执行的函数接收四个参数:前一个值(就是上一次操作结果的值)、当前值、当前值在数组中的索引值、以及数组本身(不一定要四个值都传递)
使用reduce求和:
1 | var nums = [1, 2, 3, 4, 5, 4, 3, 2, 1] |