基本语法

声明数组:

  1. let arr = ['第一','第二','第三']
  2. //or
  3. let arr = new Array('第一','第二','第三')

第一个就可以了。

数组从0开始,通过下标指定想要获取数组里面的值:

  1. arr[0] //'第一'
  2. arr[1] //'第二'
  3. arr[2] //'第三'

可通过下标指定的值,替换内容,如:

  1. arr[0] = "修改了第一的内容"
  2. console.log(arr) // ["修改了第一的内容",'第二','第三']

也可以自己在数组后面手动添加内容,例如:

  1. arr[3] = "自己添加了第四"
  2. console.log(arr) // ["修改了第一的内容",'第二','第三',"自己添加了第四"]

当然,数组有 length 得出数组的值:

  1. console.log(arr.length) // 4

数组的内容可以是任何类型:

  1. let arr = ['第一', {name: 'John'}, true, function(){consoel.log('hellow')}]
  2. consoel.log(arr[1].name) //"John"
  3. arr[3]() //'hellow'

数组方法

pop/push

pop方法是把数组末端最后的元素取出来并返回,如:

  1. let arr = ['第一','第二','第三']
  2. arr.pop() // '第三'
  3. console.log(arr) // ['第一','第二']

push与pop相反,在数组末端添加一新元素:

  1. let arr = ['第一','第二','第三']
  2. arr.pop("添加第四")
  3. console.log(arr) // ['第一','第二','第三',"添加第四"]

shift/unshift

与上面的类似,只不过专门针对数组首端

shift方法,把数组的第一个元素取出来并返回, 并且后面的元素就会往前排,例如原本下标为1的元素就变成下标为0 :

  1. let arr = ['第一','第二','第三']
  2. console.log(arr[0]) // '第一'
  3. arr.shift() // '第一'
  4. console.log(arr) // ['第二','第三']
  5. console.log(arr[0]) // '第二'

unshift方法,类似的,在首端前面新增一个元素,后面的元素就需要往后排:

  1. let arr = ['第一','第二','第三']
  2. console.log(arr[0]) // '第一'
  3. arr.unshift('新增一个第一') // '第一'
  4. console.log(arr) // ['新增一个第一','第一','第二','第三']
  5. console.log(arr[1]) // '第一'

上面四种方法,允许开发者在一个数组的前后两端进行新增、删除操作,就类似于栈,遵循“先进后出”原则,在计算机科学里,这样的数据结构称之为“双端队列”。

性能

以上四种方法是有性能区别的, pushpop 性能比 shiftunshift 快。元素越多,该性能区别越明显。
image.png
因为shiftunshift 对数组的前端操作,每操作一次,后面的数组的下标就要变化一次,元素越多,所花的时间就越多。

数组的特殊之处

在JS中,只有8种原始类型,分别是:Number,String、Boolean、Bight、null、undefined、symbol、object。并没有数组类型,也就是说,JS的数组是一个特殊的对象。即object类型!

也就是说,数组可以像对象一样使用,甚至还可以如下:

  1. let arr = ['第一','第二','第三']
  2. arr[9999] = 'a' //分配索引值远大于原数组的长度的属性,中间什么都没有
  3. arr[8888] = 'b' //倒序填充属性
  4. arr.name = '小名' //像对象一样给数组一个属性

以上就不要用了,像正常的数组对待即可。

遍历数组

最原始的遍历就是直接使用 for 语句:

  1. let arr = [1,2,3]
  2. for (let i = 0; i < arr.length; i++){
  3. console.log(arr[i])
  4. }

还有一种遍历方法,使用 for...fo

  1. let arr = [1,2,3]
  2. for(let arr of arrs){
  3. console.log(arr)
  4. }

因为数组也是对象,所以可以使用 for...in

  1. let arrs = [1,2,3]
  2. for(let key in arrs){
  3. console.log(arrs[key])
  4. }

但是该方法存在一定的危险,for...in 语句会遍历所有的属性,因为数组是对象,该语句会遍历length和索引属性。所以在数组建议不使用for...in 语句,而是使用for...fo ,普通对象就可以使用for...in

数组方法进阶

除了以上提到的4个方法,还有其他的方法。

splice

多功能瑞士刀,功能兼具以上方法,也就是可以增加、删除、插入。语法:

  1. let arrs = [1,2,3]
  2. arrs.splice(state[, deleteCount, elem1,...,elemN])

start 指的是arr的下标,往后开始修改。 deleteCount ,删除N个元素并插入 elem1,...,elemN ,然后返回已经被删除的元素。例如:

  1. arrs.splice(1,1,'小明') //返回已经删除的[2]
  2. console.log(arrs) //[1,'小明',3]
  3. //or
  4. let arr = arrs.splice(1,1,'小明','小红')
  5. console.log(arr) //[2]
  6. console.log(arrs) //[1,'小明','小红',3]

slice

复制数组到一个新的数组。

语法:

  1. arr.slice(start, end)

返回一个数组,将从start到end(不包括end)的数组复制到一个新的数组。如:

  1. let arrs = [1,2,3]
  2. let arr1 = arrs.slice(0,2)
  3. console.log(arr1) //[1,2]
  4. //也可以
  5. let arr1 = arrs.slice() //全部复制

concat

创建一个新数组,其中包括来自其他数组和其他项的值。

语法:

  1. arr.concat(arg1, arg2, ...,argN)

如:

  1. let arrs = [1,2,3]
  2. let arrs1 = ["小明","小红"]
  3. let arrx = arrs.concat(arrs1, [3,4,5,6,7,],33,44,55)
  4. console.log(arrx) //[1, 2, 3, "小明", "小红", 3, 4, 5, 6, 7, 33, 44, 55]

forEach

为数组里面的每个元素都运行一个函数:

如:

  1. ["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
  2. console.log(`${item} is at index ${index} in ${array}`)
  3. });

image.png

数组搜索

在数组中搜索想要的元素,有几种方法。

indexOf、lastIndexOf、includes

  • indexOf(item,from) 从索引 from 开始搜索 item ,找到返回索引,没有返回-1。
  • lastIndexOf(item, from) 作用同上,只是从右往左的去查找。
  • includes(item, from) 作用一样,但查找的时候如果有,返回true,反之返回false

例如:

  1. let arr = [1, 0, false]
  2. console.log(arr.index(0)) //1
  3. console.log(arr.index(false)) //2
  4. console.log(arr.index(null)) //-1
  5. console.log(arr.includes(1)) //true

注意,includes 可以比较精准的查找到NaN:

  1. const arr = [1,2,3,NaN,5]
  2. console.log(arr.indexOf(NaN)) //-1
  3. console.log(arr.includes(NaN)) // 3

find 与 findIndex

假如有个对象数组,我要怎么查找某个对象里面的元素呢?这里就用到了find。语法如下:

  1. arr.find(function(item, index, array){
  2. //如果找到,就会返回true,并停止迭代且返回item
  3. //如果没有,则返回undefined
  4. })

该方法依次对数组中的每个元素调用该函数:

  • item 是元素
  • index 是数组的索引
  • array 是数组本身

例如:

  1. let users = [
  2. {id: 1, name: '小明'},
  3. {id: 2, name: '小红'}
  4. ]
  5. let user = users.find(item => item.id === 1)
  6. console.log(user.name) //'小明'

findIndexfind 是一样的语法,但是如果找到元素,就会返回元素的索引,而不是元素的本身,反之返回-1。

filter

在迭代对象数组时,如果搜索条件为ture的对象,就返回并继续迭代。语法与 find 是一致的,如:

  1. let users = [
  2. {id: 1, name: "小明"},
  3. {id: 2, name: "小红"},
  4. {id: 3, name: "小黄"}
  5. ];
  6. let user = users.filter(item => item.id > 1)
  7. console.log(user[0].name) //"小红"

转换数组

map

对数组的每个元素都调用函数,并返回结果数组。语法与 find 一样:

  1. let result = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length)
  2. console.log(result) //[5,7,6]

sort

该方法对数组进行原位(即对原数组进行修改)排序,更改数组的顺序,并返回排序后的数组:

  1. let arr = [1,2,15]
  2. arr.sort() //如果不传参,就会按照字符串的字典排序,结果如下
  3. console.log(arr) //[1,15,2]

传参后:

  1. function compareNumeric(a, b){ //注意,sort这个方法是两两比较的,所以这里也是两个参数
  2. if(a > b) return 1;
  3. if (a == b) return 0;
  4. if (a < b) return -1;
  5. }
  6. let arr = [1,2,15]
  7. arr.sort(compareNumeric)
  8. console.log(arr) //[1, 2, 15]

以上的代码可以简化:

  1. let arr = [1,2,15]
  2. arr.sort((a,b) => a - b)
  3. console.log(arr) //[1, 2, 15]

reverse

该方法可用于颠倒数组中的元素的顺序。例如:

  1. let arr = [1,2,3,4,5,6,7,8]
  2. arr.reverse()
  3. console.log(arr) // [8, 7, 6, 5, 4, 3, 2, 1]

split 和 join

split 是用于分隔一个字符串,返回数组,如:

  1. let str = 'Bilbo, Gandalf, Nazgul';
  2. let arr = str.split(",")
  3. console.log(arr) //['Bilbo', 'Gandalf', 'Nazgul']

该方法有个可选项,可以限定长度,如:

  1. let str = 'Bilbo, Gandalf, Nazgul';
  2. let arr = str.split(",", 2)
  3. console.log(arr) //['Bilbo', 'Gandalf']

如果参数为空字符串,会:

  1. let str = "string"
  2. let arr = str.split('')
  3. console.log(arr) //["s", "t", "r", "i", "n", "g"]

join 相反,把数组的所有元素连接成一个字符串:

  1. let arr = ["s", "t", "r", "i", "n", "g"]
  2. let str = arr.join('+')
  3. console.log(str) //'s+t+r+i+n+g'

reduce 和 reduceRight

forEachmap 差不多,也是为数组内的每个元素都执行一次,但是这个用法稍微复杂点。语法如下:

  1. let value = arr.reduce(function(accumulator, item, index, array){
  2. // ...
  3. }, [initial])

参数讲解:

  • accumulator :是上一个函数的调用结果,初始化的时候就等于 initial (前提提供了 initial
  • item :当前数组的元素。
  • index :当前数组的元素的下标。
  • array :数组本身。
  • initial :初始值,如果不事先设置,则默认把数组的第一个元素当作初始值。

例子:

  1. let result1 = arr.reduce((sum, current, a, b) => {
  2. sum + current;
  3. console.log(`index: ${a}, arr: ${b}`)
  4. }, 0)

结果:
image.png
这个运行过程:

  • sum(accumulator)的初始值为 initial ,而current( item )为遍历的第一个元素,即值为1,所以 1+0 结果就为1 。
  • 上一次的结果为1 ,所以 sum = 1 ,然后current遍历的第2个元素为2,所以 1+2 的值为3.
  • 以此类推。。。。

流程图:
image.png

reduceRight 如方法名一样,遍历是从右往左,作用一样。

Array.isArray

该方法作用是判断数组是否是数组!

由于数组是基与对象的,所以判断原始类型的 typeof 判断数组的结果只能是对象。如下 :

  1. let arr = []
  2. typeof(arr) //"object"
  3. Array.isArray(arr) //true

关于数组方法里的this

大多数的方法参数最后是有可选参数的,这个可选参数是 thisArg ,例如:

  1. arr.find(func, thisArg);
  2. arr.filter(func, thisArg);
  3. arr.map(func, thisArg);
  4. //...

thisArg 的值就是 functhis 。例如:

  1. let army = {
  2. minAge: 18,
  3. maxAge: 27,
  4. canJoin(user){
  5. console.log(`minAge:${this.minAge}, maxAge:${this.maxAge}`) //minAge:18, maxAge:17
  6. return user.age >= this.minAge && user.age < this.maxAge
  7. }
  8. }
  9. let users = [
  10. {age: 16},
  11. {age: 19},
  12. {age: 26},
  13. {age: 32}
  14. ]
  15. let arr = users.filter(army.canJoin, army)
  16. console.log(arr[0].age) //16

如果不给 thisArg 参数,那么 this = undefined
当然,上面的第15行代码可以换成如下更好理解:

  1. let arr = users.filter(user => army.canJoin(user))

总结

数组添加删除操作:

  • pop —— 末端最后一个元素被取出并返回
  • push —— 末端添加一个新的元素
  • shift —— 首端第一个元素被取出并返回
  • unshift —— 首端新添加一个新的元素

数组万能操作:

  • splice(state[,deleteCount, ..., items) —— 从 state 开始删除 deleteCount 个元素,并插入 items(原位in-place: 对,操作自身的,不会创建新的数) 。
  • slice(state, end) —— 从索引 state 开始到索引 end (不包括 end )的元素复制到新的数组。
  • concat(...items) —— 返回一个新的数组,复制当前数组所有元素,并向其中添加 items 。如果 items 里也有数组,那么把这个数组里面的元素复制出了。

遍历操作:

  • forEach(func) —— 为每个元素执行一次函数,可以修改里面的元素,并不会返回任何内容。

数组搜索:

  • indexOf(from, item) / lastIndex(from, item) —— 从 from 开始查找数组内是否有想要 item ,有返回该元素,无返回-1。
  • find(func) —— 为每个元素执行一次函数,如果使得 func 返回 true ,就返回这个的值,并停止迭代;没有就返回 undefined
  • findIndex(func) —— 同上,只不过 ture 只会返回索引下标而不是值。
  • filter(func) —— 与 find 类似,但如果执行到 true 就会返回并继续迭代直到结束。

数组转换:

  • map(func) —— 为数组内的每个元素执行一次函数,与 forEach 是差不多的,但是这个不会修改数组里面的元素,会返回新的数组。
  • sort(func) —— 对原来的数组进行排序(原位in-place),然后返回。
  • reverse() —— 对原来的数组进行反转,然后返回(也是原位in-place)
  • splite() —— 对字符串进行切割并返回数组。
  • join() —— 对数组进行拼接成字符串。
  • reduce(func[, initial]) / reduceRight(func[, initial]) —— 对数组里的每个元素执行一次函数,并把函数的结果传递给下一次的执行。

数组判断:

  • Array.isArray(arr) 判断是否是数组。