淘先锋技术网

首页 1 2 3 4 5 6 7

javaScript Array api梳理

一、Array 类型检测

  1. Array.isArray
  2. instanceof
  3. Array.prototype.isPrototypeOf
  4. Object.getPrototypeOf
  5. constructor
  6. Object.prototype.toString.apply
let is_array1 = Array.isArray([]) // true
let is_array2 = ([]) instanceof Array // true
let is_array3 = Array.prototype.isPrototypeOf([]) // true
let is_array4 = Object.getPrototypeOf([]) === Array.prototype // true
let is_array5 = ([]).constructor === Array // true
/**
* 推荐使用下面检测方式
*/
let is_array6 = Object.prototype.toString.apply([]) === '[object Array]' // true

二、数组构造函数有几种?

  1. Array 构造函数
let arr_new_array1 = new Array() // []
let arr_new_array2 = new Array('4') // ['4']
let arr_new_array3 = new Array('4.0') // ['4.0']
let arr_new_array4 = new Array('4.1') // [4.1']
let arr_new_array5 = new Array(4) // [empty*4]
let arr_new_array6 = new Array(4.0) // [empty * 4]
let arr_new_array7 = new Array(4, 5) // [4, 5] 参数的length 大于1时 直接将参数依次转化为数组中的一项, 返回的新数组
/**
*  下面是两种方式会报错
*/
try {
  // 这里直接报错 Array 数字类型 不是整数时报错
  var arr_new_array8 = new Array(4.1) // error
  // 这里直接报错 Array 数字类型 不是正整数时报错
  var arr_new_array9 = new Array(-1) // error
} catch (e) {
  console.error(e)
}
  1. Array.of 构造方法
/**
 * Array.of 构造方法
 * 参数依次转化为数组中的一项, 返回的新数组
 */
let arr_new_array_of1 = Array.of() // []
let arr_new_array_of2 = Array.of(1) // [1]
let arr_new_array_of3 = Array.of('1') // ['1']
let arr_new_array_of4 = Array.of(1, 2, 3, 4) // [1,2,3,4]
let arr_new_array_of5 = Array.of('1', 2, '3', 4) // ['1',2,'3',4]
  • Array.from 构造方法
/**
 * Array.from 构造方法
 *   arrayLike 想要转换成数组的伪数组对象或可迭代对象
 *   mapFn { Funtion } 可选  新数组中的每个元素都会执行该回调函数
 *   thisArg 可选 执行回到函数 mapFn 时 this 对象
 */
const ArrayFromObj = {0: 'one', 1: 'two', length: 2}
let arr_new_array_from = Array.from(ArrayFromObj, function (item, index) {
  console.log(this) // {test: 'thisObj'} 如果箭头函数 this 指向 该函数所在的作用域
  return `${item} - ${index}` // 如果不设置返回默认 返回undefined
}, {test: 'thisObj'}) // ['one - 0', 'two - 1']

三、影响改变原数组的方法
基于 ES6,会改变自身值的方法一共有 9 个,shift、unshift、pop、push、reverse、sort 、splice,以及两个 ES6 新增的方法 fill 和 copyWithin。

/**
 * 影响改变原数组的方法
 *  shift       将第1个元素删除,返回删除元素
 *  unshift     向数组开头添加元素,返回数组的长度
 *  pop         删除最后一个元素,返回删除元素
 *  push        向数组末尾添加元素,返回数组的长度
 *  reverse     颠倒数组顺序
 *  sort        对数组排序
 *  splice      删除/增加/替换数组元素,返回被删除元素数组
 *  ES6:
 *    fill        固定值填充一个数组中从起始索引到终止索引内的全部元素, 返回数组本身
 *    copyWithin  浅复制数组的一部分到同一数组中的另一个位置, 返回数组本身
 */
let array = [1, 2, 3, 4, 5]
const array_shift = array.shift()
console.log(array) // [2,3,4,5]
console.log(array_shift) // 1

array = [1, 2, 3, 4, 5]
const array_unshift = array.unshift(1, 2, 3)
console.log(array) // [1, 2, 3, 1, 2, 3, 4, 5]
console.log(array_unshift) // 8

array = [1, 2, 3, 4, 5]
const array_pop = array.pop()
console.log(array) // [1,2,3,4]
console.log(array_pop) // 5

array = [1, 2, 3, 4, 5]
const array_push = array.push(1, 2, 3)
console.log(array) // [1,2,3,4,5,1,2,3]
console.log(array_push) // 8

array = [1, 2, 3, 4, 5]
const array_reverse = array.reverse()
console.log(array) // [5,4,3,2,1]
console.log(array_reverse) // [5,4,3,2,1]

array = [100, 2, 3, 4, 5]
const array_sort1 = array.sort() // 没有回调函数 默认Unicode排序
console.log(array) // [100,2,3,4,5]
console.log(array_sort1) // [100,2,3,4,5]

array = [100, 2, 3, 4, 5]
/**
 * sort((a, b) => ...) 回调函数
 *  return 
 *          小于 0, a 会排列到 b 之前
 *          大于 0, b 会排列到 a 之前
 *          等于 0, a、b 位置不变
 */
const array_sort2 = array.sort((a, b) => a - b) // 升序排列数组
console.log(array) // [2,3,4,5,100]
console.log(array_sort2) // [2,3,4,5,100]

array = [1, 2, 3, 4, 5]
/**
 * splice(start[, deleteCount[, item1[, item2[, ...]]]])
 * 参数:
 *    start 开始位置
 *    deleteCount 删除个数 【可选】 如果没有值 默认为 length - start
 *    item1,item2..... 从 start 位置开始添加这些元素 【可选】 如果没有则不添加 只删除 元素
 */
const array_splice = array.splice(1, 2, 30, 40, 50)
console.log(array) // [1,30,40,50,4,5]
console.log(array_splice) // [2,3]

array = [1, 2, 3, 4, 5]
/**
 * fill(value[, start[, end]])
 * value 填充值 
 * start 开始位置【可选】 默认 0
 * end   结束位置 【可选】 默认 length
 */
const array_fill = array.fill(8, 1, 4)
console.log(array) // [1,8,8,4,5]
console.log(array_fill) // [1,8,8,8,5]

array = [1, 2, 3, 4, 5]
/**
 * copyWithin(target[, start[, end]])
 * target 复制序列到该位置 
 * start 开始复制位置【可选】 默认 0
 * end   结束复制位置 【可选】 默认 length
 */
const array_copyWithin = array.copyWithin(1, 4, 5)
console.log(array) // [1,5,3,4,5]
console.log(array_copyWithin) // [1,5,3,4,5]

四、不影响自身的方法
基于 ES10,不会改变自身的方法也有 10 个, join、 concat 、slice、toString、toLocaleString、indexOf、lastIndexOf,ES7新增的 includes ,及ES10新增的 flat、flatMap方法。

/**
 * 不影响改原数组的方法
 *  join             元素连接成一个字符串并返回这个字符串
 *  concat           合并两个或多个数组,返回新数组
 *  slice            从数组中选定的元素,返回新数组
 *  toString         以,号拼接数组元素,返回字符串
 *  toLocaleString   返回一个字符串表示数组中的元素
 *  indexOf          查找元素是否存在该数组中,返回该元素在数组的下标,没有返回 -1
 *  lastIndexOf      从后面开始查找元素是否存在该数组中,返回该元素在数组的下标,没有返回 -1
 *  ES7:
 *    includes       判断一个数组是否包含一个指定的元素, 返回 Boolean
 *  ES10:
 *    flat           按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回
 *    flatMap        使用映射函数映射每个元素,然后将结果压缩成一个新数组
 */
let array = [1,2,3,4,5,6]
const array_join = array.join('-') // 指定拼接字符,不指定默认为,
console.log(array.join()) // 1,2,3,4,5,6 
console.log(array_join) // 1-2-3-4-5-6

const array_concat1 = array.concat([7,8], [9, 10]) // [1,2,3,4,5,6,7,8,9,10]
const array_concat2 = array.concat(7, [8], [9, 10]) // [1,2,3,4,5,6,7,8,9,10]
console.log(array_concat1) // [1,2,3,4,5,6,7,8,9,10]
console.log(array_concat2) // [1,2,3,4,5,6,7,8,9,10]
console.log(array) // [1,2,3,4,5,6]

const array_slice1 = array.slice() // 不指定位置选定全部元素
const array_slice2 = array.slice(1) // 从指定位置1开始, 没有指定结束位置 默认为length
const array_slice3 = array.slice(2,5) // 选定下标 2-4(结束位置前一个)的元素
console.log(array_slice1) // [1,2,3,4,5,6]
console.log(array_slice2) // [2,3,4,5,6]
console.log(array_slice3) // [3,4]

const array_toString = array.toString()
console.log(array_toString) // '1,2,3,4,5,6'

const array_toLocaleString = array.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }) // 不太清楚这里配置 没有深入
console.log(array_toLocaleString) // '¥1,¥2,¥3,¥4,¥5,¥6'

// 注意: 如果数组中有0 -0 与 +0 是相匹配能查询到返回其所在下标
const array_indexOf1 = array.indexOf('1')
const array_indexOf2 = array.indexOf(3)
const array_indexOf3 = array.indexOf() // 如果数组中有undefined元素 返回其下标
console.log(array_indexOf1) // -1
console.log(array_indexOf2) // 2
console.log(array_indexOf3) // -1
// 注意: 如果数组中有0 -0 与 +0 是相匹配能查询到返回其所在下标
const array_lastIndexOf1 = array.lastIndexOf('1')
const array_lastIndexOf2 = array.lastIndexOf(3)
const array_lastIndexOf3 = array.lastIndexOf() // 如果数组中有undefined元素 返回其下标
console.log(array_lastIndexOf1) // -1
console.log(,array_lastIndexOf2) // 2
console.log(array_lastIndexOf3) // -1
// 注意: 如果数组中有0 -0 与 +0 是相匹配能查询到返回其所在下标
const array_includes1 = array.includes('1')
const array_includes2 = array.includes(1)
const array_includes3 = array.includes() // 如果数组中有undefined元素 返回为true
console.log(array_includes1) // false
console.log(array_includes2) // true
console.log(array_includes3) // false

var flatArray = [1,[2,[3],[4]],5,[[[[[6]]]]],7,[8,[9]]]
const array_flat1 = flatArray.flat() // 不指定解层次默认为1
const array_flat2 = flatArray.flat(2) // 2层
const array_flat3 = flatArray.flat(Infinity) // 无限层次
const array_flat4 = flatArray.flat(0) // 0或者负数都 将 array元素进行浅拷贝
console.log(array_flat1) // [1,2,[3],[4],5,[[[[6]]]],7,8,[9]]
console.log(array_flat2) // [1,2,3,4,5,[[[6]]],7,8,9]
console.log(array_flat3) // [1,2,3,4,5,6,7,8,9]
console.log(array_flat4) // [1,[2,[3],[4]],5,[[[[[6]]]]],7,[8,[9]]]

const array_flatMap1 = flatArray.flatMap(item => item)
console.log(array_flatMap1) // [1,2,[3],[4],5,[[[[6]]]],7,8,[9]]

五、遍历的方法
基于 ES6,不会改变自身的遍历方法一共有 12 个,分别为 forEach、every、some、filter、map、reduce、reduceRight,以及 ES6 新增的方法 entries、find、findIndex、keys、values。

/**
 * 遍历/循环方法
 *  map               创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值
 *  forEach           数组的每个元素执行一次给定的函数
 *  some              测试数组中是不是至少有1个元素通过了被提供的函数测试,返回Boolean 有一个符合就不再执行循环
 *  every             测试一个数组内的所有元素是否都能通过某个指定函数的测试, 返回Boolean 有一个不符合就不再执行循环
 *  filter            循环一个数组,返回符合条件的元素数组  
 *  reduce            数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
 *  reduceRight       数组中的每个元素执行一个由您提供的reducer函数(降序执行),将其结果汇总为单个返回值。
 *  ES6:
 *      keys           返回一个包含数组中每个索引键的Array Iterator对象, 通过Array Iterator对象的next方法获取到值 next 返回对象 {value: ---, done: Boolean} 如果done 为true 则到最后
 *      values         返回一个包含数组中每个索引键的值的Array Iterator对象, 通过Array Iterator对象的next方法获取到值 next 返回对象 {value: ---, done: Boolean} 如果done 为true 则到最后
 *      find           返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined
 *      findIndex      返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1
 *      entries        返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对
 */
// forEach方法
var array = [1, 3, 5]
var obj = { name: 'test' }
var forEachReturn = array.forEach(function(value, index, array){ // 如果箭头函数 this 指向 该函数所在的作用域
  console.log(value) // 1 3 5
  console.log(this.name) // test被打印了三次, this指向obj
}, obj)
console.log(array) // [1, 3, 5]
console.log(forEachReturn) // undefined

// every方法
var o = [10, 20, 30, 40]
var bool = o.every(item => item >= 10)
console.log(bool) // true

// some方法
var array = [0, 1, 2, 3, 6]
var isExist = array.some(function(value, index, array){
  return value > 5
})
console.log(isExist) // true 

// map 方法
var array = [1, 2, 3, 3, 6]
array.map(item => item + 1)
console.log(array)  // [2, 3, 4, 4, 7]

// filter 方法
var array = [10, 20, 30, 30, 60]
var array_filter = array.filter(function(value, index, array){
  return value > 20
})
console.log(array_filter) // [30, 30, 60]

/**
* reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
* 	callback  执行数组中每个值 (如果没有提供 initialValue则第一个值除外)的函数,包含四个参数:
* 		accumulator 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(见于下方)。
*       currentValue 数组中正在处理的元素。
*       index 【可选】  数组中正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则从索引1起始。
*       array 【可选】调用reduce()的数组
*    
*   initialValue 【可选】作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。
*
*/
var array = [1, 2, 3, 4]
var array_reduce = array.reduce(function(accumulator, currentValue, index, array){
  return accumulator * currentValue
}, 4)
console.log(array_reduce) // 96
// ES6写法更加简洁 这里不设置 initialValue 参数
array.reduce((t, v) => t * v) // 24

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

// entries方法
var array = ["one", "two", "three"]
var iterator = array.entries()
console.log(iterator.next().value) // [0, "one"]
console.log(iterator.next().value) // [1, "two"]
console.log(iterator.next().value) // [2, "three"]
console.log(iterator.next().value) // undefined, 迭代器处于数组末尾时, 再迭代就会返回undefined

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

// keys方法
[...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方法
var array = ["a", "b"]
var iterator = array.values()
console.log(iterator.next().value) // a
console.log(iterator.next().value) // b
console.log(iterator.next().value) // undefined
标准构造函数/方法改变自身方法不改变自身方法遍历的方法
ES5及以前Arrayshift、unshift、pop、push、reverse、sort 、splicejoin、 concat 、slice、toString、toLocaleString、indexOf、lastIndexOfforEach、every、some、filter、map、reduce、reduceRight
ES6/7/8/10Array.of、Array.fromfill、copyWithinincludes、flat、flatMapentries、find、findIndex、keys、values

最后还有两个非标准 api,at与toSource,这里就不介绍了,有兴趣的同学可以到mdn查询;