JavaScript 数组 API 梳理

1,192 阅读7分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

Array 的构造

构造器

通常使用对象字面量的方式来创建一个数组,类似于 var a = [] 这种,但是,总有对象字面量表述乏力的时候,比如,我想创建一个长度为 6 的空数组,用对象字面量的方式是无法创建的,因此只能写成下述代码这样。

// 使用 Array 构造器,可以自定义长度
var a = Array(6) // [empty × 6]
// 使用对象字面量
var b = []
b.length = 6     // [undefined × 6]

Array 构造器根据参数长度的不同,有如下两种不同的处理方式:

  • new Array(arg1, arg2,…) ,参数长度为 0 或长度大于等于 2 时,传入的参数将按照顺序依次成为新数组的第 0 至第 N 项(参数长度为 0 时,返回空数组);
  • new Array(len) ,当 len 不是数值时,处理同上,返回一个只包含 len 元素一项的数组;当 len 为数值时,len 最大不能超过 32 位无符号整型,即需要小于 2 的 32 次方(len 最大为 Math.pow(2,32)),否则将抛出 RangeError

Array.ofArray.from

Array.of

Array.of 用于将参数依次转化为数组中的一项,然后返回这个新数组,而不管这个参数是数字还是其他。

当参数为两个时,返回的结果是一致的;当参数是一个并且是正整数时,Array.of 会把参数变成数组里的一项,而构造器则会生成长度和第一个参数相同的空数组。

Array.of(8)     // [8]
Array(8)        // [empty × 8]
Array.of(8, 5)  // [8, 5]
Array(8, 5)     // [8, 5]
Array.of('8')   // ["8"]
Array('8')      // ["8"]
Array.of(9.8)   // [9.8]
Array(9.8)      // Uncaught RangeError: Invalid array length

Array.from

Array.from 可以从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。

Array.from(arrayLike[, mapFn[, thisArg]])

Array.from 接收三个参数:

  1. 类似数组的对象,必选;
  2. 加工函数,新生成的数组会经过该函数的加工再返回,可选;
  3. this 作用域,表示加工函数执行时 this 的值,可选。
var obj = {0: 'a', 1: 'b', 2:'c', length: 3}
var newObj = Array.from(obj, function(value, index){
  console.log(value, index, this, arguments.length)
  return value.repeat(3)  //必须指定返回值,否则返回 undefined
}, obj)
console.log(newObj)   // ['aaa', 'bbb', 'ccc']

image.png

上述代码可以简化使用箭头函数来实现。

Array.from(obj, (value) => value.repeat(3));   // ['aaa', 'bbb', 'ccc']

除了对象外,拥有迭代器的对象还包括 StringSetMap 等,Array.from 统统可以处理。

// String
Array.from('abc')        // ["a", "b", "c"]
// Set
Array.from(new Set(['abc', 'def']))  // ["abc", "def"]
// Map
Array.from(new Map([[1, 'ab'], [2, 'de']]))  // [[1, 'ab'], [2, 'de']]

改变自身的方法

改变自身值的方法一共有 9 个,分别为 poppushreverseshiftsortspliceunshift,以及两个 ES6 新增的方法 copyWithinfill

// pop方法 从数组中删除最后一个元素,并返回该元素的值。
var array = ["cat", "dog", "cow", "chicken", "mouse"]
var item = array.pop()
console.log(array) // ["cat", "dog", "cow", "chicken"]
console.log(item)  // mouse

// push方法 将一个或多个元素添加到数组的末尾,并返回该数组的新长度。
var array = ["football", "basketball",  "badminton"]
var i = array.push("golfball")
console.log(array) // ["football", "basketball", "badminton", "golfball"]
console.log(i)     // 4

// reverse方法 将数组中元素的位置颠倒,并返回该数组。
var array = [1,2,3,4,5]
var array2 = array.reverse()
console.log(array)             // [5,4,3,2,1]
console.log(array2===array)    // true

// shift方法 从数组中删除第一个元素,并返回该元素的值。
var array = ['a', 'b', 'c', 'd', 'e']
var item = array.shift()
console.log(array)  // ['b', 'c', 'd', 'e']
console.log(item)   // 'a'

// unshift方法 将一个或多个元素添加到数组的开头,并返回该数组的新长度
var array = ["red", "green", "blue"]
var length = array.unshift("yellow")
console.log(array)    // ["yellow", "red", "green", "blue"]
console.log(length)   // 4

// sort方法 对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的
var array = ["apple","Boy","Cat","dog"]
var array2 = array.sort()
console.log(array)            // ["Boy", "Cat", "apple", "dog"]
console.log(array2 == array)  // true

// splice方法 通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
var array = ["apple","boy"]
var splices = array.splice(1,1)
console.log(array)       // ["apple"]
console.log(splices)     // ["boy"]

// copyWithin方法 浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度
var array = [1,2,3,4,5]
var array2 = array.copyWithin(0,3)
console.log(array===array2, array2)  // true [4, 5, 3, 4, 5]

// fill方法 用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
var array = [1,2,3,4,5]
var array2 = array.fill(10,0,3)
console.log(array===array2,array2)  // true [10, 10, 10, 4, 5], 可见数组区间[0,3]的元素全部替换为10

不改变自身的方法

不会改变自身的方法也有 9 个,分别为 concatjoinslicetoStringtoLocaleStringindexOflastIndexOf、未形成标准的 toSource,以及 ES7 新增的方法 includes

// concat方法 用于合并两个或多个数组,返回一个新数组。
var array = [1, 2, 3]
var array2 = array.concat(4,[5,6],[7,8,9])
console.log(array2) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(array)  // [1, 2, 3] 原数组并未被修改

// join方法 将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。
var array = ['We', 'are', 'Chinese'];
console.log(array.join())      // "We,are,Chinese"
console.log(array.join('+'))   // "We+are+Chinese"

// slice方法 返回一个新的数组对象,由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括 end)
var array = ["one", "two", "three","four", "five"]
console.log(array.slice())      // ["one", "two", "three","four", "five"]
console.log(array.slice(2,3))   // ["three"]

// toString方法 返回一个字符串,表示指定的数组及其元素。
var array = ['Jan', 'Feb', 'Mar', 'Apr']
var str = array.toString()
console.log(str)       // Jan,Feb,Mar,Apr

// tolocalString方法 返回一个字符串表示数组中的元素。数组中的元素将使用各自的 toLocaleString 方法转成字符串。
var array= [{name:'zz'}, 123, "abc", new Date()]
var str = array.toLocaleString()
console.log(str)     // [object Object],123,abc,2021/10/26 下午4:44:53

// indexOf方法 返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
var array = ['abc', 'def', 'ghi', '123']
console.log(array.indexOf('def'))     // 1
console.log(array.indexOf('def3'))     // -1

// includes方法 用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
var array = [-0, 1, 2]
console.log(array.includes(+0))    // true
console.log(array.includes(1))     // true
console.log(array.includes(3))     // false
var array = [NaN]
console.log(array.includes(NaN))   // true

数组遍历的方法

基于 ES6,不会改变自身的遍历方法一共有 12 个,分别为 forEacheverysomefiltermapreducereduceRight,以及 ES6 新增的方法 entriesfindfindIndexkeysvalues

// forEach方法 对数组的每个元素执行一次给定的函数。
var array = [1, 3, 5]
var sReturn = array.forEach(item => {return item + 1})
console.log(array)     // [1, 3, 5]
console.log(sReturn)   // undefined, 可见返回值为undefined

// every方法 测试一个数组内的所有元素是否都能通过某个指定函数的测试,返回一个布尔值。
var arr = [2, 4, 6]
var bool = arr.every(item => item % 2 === 0)
console.log(bool)   // true

// some方法 测试数组中是不是至少有1个元素通过了被提供的函数测试,返回一个布尔值
var array = [18, 9, 10, 35, 80]
var isExist = array.some(item => item > 16);
console.log(isExist) // true 

// map 方法 创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
var array = [18, 9, 10, 35, 80]
array.map(item => item + 1);
console.log(array)  // [19, 10, 11, 36, 81]

// filter 方法 创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
var array = [18, 9, 10, 35, 80]
var array2 = array.filter(item => item > 20)
console.log(array2) // [35, 80]

// reduce方法
var array = [1, 2, 3, 4];
var s = array.reduce(function(prev, value, index, array){
  return prev * value
},1)
console.log(s) // 24
array.reduce((p, v) => p * v) //  ES6写法更加简洁 24

// reduceRight方法 (和reduce的区别就是从后往前累计)
var array = [1, 2, 3, 4]
array.reduceRight((p, v) => p * v) // 24

// entries方法 返回一个新的 Array Iterator 对象,该对象包含数组中每个索引的键/值对。
var array = ["a", "b", "c"]
var iterator = array.entries()
console.log(iterator.next().value) // [0, "a"]
console.log(iterator.next().value) // [1, "b"]
console.log(iterator.next().value) // [2, "c"]
console.log(iterator.next().value) // undefined, 迭代器处于数组末尾时, 再迭代就会返回undefined

// find & findIndex方法 find返回的元素本身,findIndex返回的元素下标
var array = [1, 3, 5, 7, 8, 9, 10]
function f(value, index, array){
  return value%2 === 0     // 返回偶数
}
function f2(value, index, array){
  return value > 20     // 返回大于20的数
}
console.log(array.find(f))         // 8
console.log(array.find(f2))        // undefined
console.log(array.findIndex(f))    // 4
console.log(array.findIndex(f2))   // -1

// keys方法 返回一个包含数组中每个索引键的 Array Iterator 对象。
[...Array(10).keys()]      // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[...new Array(10).keys()]  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

// values方法 返回一个新的 Array Iterator 对象,该对象包含数组每个索引的值
var array = ["abc", "xyz"]
var iterator = array.values()
console.log(iterator.next().value)  //abc
console.log(iterator.next().value)  //xyz

最后说一句

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下,您的支持是我坚持写作最大的动力,多谢支持。