JavaScript ES(6-11)全版本语法 (三):Array

277 阅读8分钟

前提概要

上一篇编写的是ES6中的解构赋值,链接:juejin.cn/post/699692… ,这次写的是ES6中Array的一些API和部分应用场景。如有不对的或者不准确的地方,欢迎大家提出😄,我也积极修改。下边开始正文:

表情.jpg

ES5 中数组遍历方式

for循环

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

forEach() 没有返回值,只是针对每个元素调用function

let arr = [1,2,3,4,2,5]
arr.forEach(function (elem, index, array) {
  console.log(elem) // 1 2 3 4 5 2
})

注意:
for循环和forEach的区别:
1、for循环当时是可以使用break和continue
2、forEach当中不可以使用break和continue,forEach循环会直接循环完当前的数组

map() 返回新的数组,每个元素为调用function的结果

let arr = [1,2,3,4,2,5]
let result = arr.map(function (value) {
  value += 1
  return value
})
console.log(arr, result) //  [1, 2, 3, 4, 2, 5] [2, 3, 4, 5, 3, 6]

注意:
forEach: 就是正常的数组循环
map: 会遍历数组当中的每一个元素,根据回调操作返回一个需要的 新的 数组,并且 不会改变 原数组的值

filter() 返回符合function条件的元素数组

filter:通过筛选的条件返回一个 新的 数组,并且 不会改变 原数组

let arr = [1,2,3,4,2,5]
let result = arr.filter(function (value) {
  return value == 2
})
console.log(arr, result) // [1, 2, 3, 4, 2, 5]  [2, 2]

some() 返回boolean,判断是否有元素符合function条件

some:在数组当中找到一个符合条件的元素,返回的是boolean类型的值(返回true或者false)

let arr = [1,2,3,4,2,5]
let result = arr.some(function (value) {
  return value == 4
})
console.log(arr, result) //  [1, 2, 3, 4, 2, 5] true

every() 返回boolean,判断每个元素都符合func条件

every: 判断当前数组当中的每一个元素是否都符合判断条件,如果每一个元素都符合返回true,只要有一个不符合就返回false(返回的是boolean类型)

let arr = [1,2,3,4,2,5]
let result = arr.every(function (value) {
  return value == 2
})
console.log(arr, result) // [1, 2, 3, 4, 2, 5] false

使用every遍历就可以做到break那样的效果,相对来说 return false 等同于 break,return true 等同于 continue。如果不写,默认是 return false。

注意:
every 的代码块中不能使用 break、continue,它会抛出异常。

reduce(function(prev,cur,index,array){},init)

reduce()方法对数组中的每个元素执行一个由自己提供的reducer函数(升序执行),将其结果汇总为单个返回值。 prev:表示上一次回调时候的返回值,如果当前是第一个回调,就表示的是初始值
cur:表示当前要处理的数组里的元素
index:表示当前要处理的数组里的元素的索引
array:表示处理的数组
init:表示初始的值

1、数组求和

let arr = [1,2,3,4,2,5]
let init
let sum = arr.reduce(function(prev,cur,index,array){
  return prev + cur
},init = 0)
console.log(sum) // 17

2、数组中取最大值

let arr = [1,2,3,4,2,5]
let max = arr.reduce(function(prev,cur){
  return Math.max(prev,cur)
},0)
console.log(max) // 5

3、数组去重

let arr = [1,2,3,4,2,5]
let newArr = arr.reduce(function(prev,cur){
  prev.indexOf(cur) == -1 && prev.push(cur)
  return prev
},[])
console.log(newArr) // [1, 2, 3, 4, 5]

4、数组对象去重

方法一:

let userList = [
  {name:'xs',age:18},
  {name:'sx',age:17},
  {name:'xs',age:17}
]
let newArr = userList.reduce(function(prev,cur){
  let nameList = prev.map(function(item){return item.name})
  return nameList.includes(cur.name) ? prev : [...prev,cur]
},[])
console.log(newArr) // [{name: "xs", age: 18},{name: "sx", age: 17}]

方法二:

let userList = [
  {name:'xs',age:18},
  {name:'sx',age:17},
  {name:'xs',age:17}
]
let obj = {} // 用来存放已经出现过的name
let userArr = userList.reduce(function(prev,cur){
  obj[cur.name] ? '' : obj[cur.name] = true && prev.push(cur)
  return prev
},[])
console.log(userArr)

5、数组转对象

let userList = [
  {name:'xs',age:18},
  {name:'sx',age:17},
  {name:'zk',age:17}
]
let userObj = userList.reduce(function(prev,cur){
  return {...prev,[cur.name]:cur.age}
},{})
console.log(userObj) // {xs: 18, sx: 17, zk: 17}

for...in

for...in 遍历数组的时候会把原型对象上声明的方法或者属性也给遍历出来,这是因为for...in是为遍历对象创造的({a:1, b:2}),不是为数组设计的。

let arr = [1,2,3,4,2,5]
Array.prototype.foo = function () {
  console.log('foo')
}
for (let i in arr) {
  console.log(i, arr[i])
}
/* 
  0 1
  1 2
  2 3
  3 4
  4 2
  5 5 
  foo ƒ () {
    console.log('foo')
  }
*/

通过打印结果可以看出for...in不能用于遍历数组。并且for...in代码块中不能有return,不然会抛出异常。

ES6 中数组遍历方式

for...of

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

for...of遍历的是一切可遍历的元素(数组、对象、集合)等。

let arr = [1,2,3,4,2,5]
// 获取数组的值
for (let item of arr.values()) {
  console.log(item) // 1 2 3 4 2 5
}
// 注:arr和arr.values()取的值是一样的

// 获取数组的下标(索引)
for (let item of arr.keys()) {
  console.log(item) // 0 1 2 3 4 5
}

// 获取数组的值和下标(索引)
for (let [index, item] of arr.entries()) {
  console.log(index, item) // 0 1  1 2  2 3  3 4  4 2  5 5
}

:for...of是支持break、continue、return的,所以在功能上非常贴近原生的 for。

Array.from()

Array.from可以把类数组(伪数组)转化为真正意思上的数组
类数组(伪数组)的类型:函数中的 arguments、DOM中的 NodeList、HTMLCollection等。类数组(伪数组)具备两个特征,1. 按索引方式储存数据 2. 具有length属性;如:let arrLike = {0: 'a',1: 'b',2: 'c',length: 3}
arguments是一个对应于传递给函数的参数的类数组对象。
HTMLCollection 类数组是通过 getElementsByTagName、getElementByClassName 取到的
NodeList 节点列表 类数组是通过 querySelectAll 取到的

把类数组(伪数组)转换为真正意义上的数组的传统做法是:

let args = [].slice.call(arguments)
let image1 = [].slice.call(document.querySelectorAll('img'))
let image2 = [].slice.call(document.getElementByClassName('.img'))

其基本原理是使用call将数组的 api 应用在新的对象上,换句话说是利用改变函数的上下文来间接使用数组的 api。 使用ES6中的Array.from(),代码如下:

let args = Array.from(arguments)
let image1 = Array.from(document.querySelectorAll('img'))
let image2 = Array.from(document.getElementByClassName('.img'))
let arrayLike = {
  0: 'es5',
  1: 'es6',
  2: 'es7',
  3: 'es8',
  length: 4
}
console.log(arrayLike) // {0: "es5", 1: "es6", 2: "es7", 3: "es8", length: 4}
let arr = Array.from(arrayLike)
arr.push('es9')
console.log(arr) // ["es5", "es6", "es7", "es8", "es9"]

Array.of()

Array.of()方法用于构建数组、数组初始化。创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。

Array.of() 和 Array 构造函数之间的区别:
在于处理整数参数:Array.of(7) 创建一个具有单个元素 7 的数组,如:let arr = Array.of(7) console.log(arr) // [7] length:1,而 Array(7) 创建一个长度为7的空数组,如:let arr = new Array(7) console.log(arr) // [empty × 7] length:7(注意:这是指一个有7个空位(empty)的数组,而不是由7个undefined组成的数组)。

Array.of(7); // [7]
Array.of(1, 2, 3); // [1, 2, 3]

Array(7); // [ , , , , , , ]
Array(1, 2, 3); // [1, 2, 3]

语法: Array.of(element0[, element1[, ...[, elementN]]])
Array.of()还可以把数据拼接成一个数组

let arrList = Array.of(18, 'xs', [1, 2, 3], false, { age: 24 })
console.log(arrList) // [18, "xs",  [1, 2, 3], false, { age: 24 }]

Array.prototype.find()

find()方法返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined。
语法arr.find(callback[, thisArg]),callback接收3个参数element、index、array

let arr = [1,2,3,4,2,5]
let res = arr.find(function (value) {
  return value == 2
})
console.log(arr, res) // [1, 2, 3, 4, 2, 5] 2

Array.prototype.findIndex()

findIndex()方法回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。其实这个和 find() 是成对的,不同的是它返回的是索引而不是值。
语法: arr.findIndex(callback[, thisArg]),callback接收3个参数element、index、array

let res = arr.findIndex(function (value) {
  return value == 2
})
console.log(arr, res) // [1, 2, 3, 4, 2, 5] 1

Array.prototype.fill()

fill()方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
语法arr.fill(value[, start[, end]])
value用来填充数组元素的值
start起始索引,默认值为0
end终止索引,默认值为 this.length

  • 数组数据填充
    let arr = new Array(3).fill(7)
    console.log(arr) //[7,7,7]
    
  • 数组替换
    let arr = [1, 2, 3, 4, 5]
    arr.fill('xs', 2, 4)
    console.log(arr) // [1,2,'xs','xs',5]
    arr.fill(0)
    console.log(arr) // [0,0,0,0,0]
    

Array.prototype.includes()

includes()方法用来判断一个数组是否包含一个指定的元素,根据情况,如果包含则返回 true,否则返回false。

let arr = [1, 2, 3, NaN]
console.log(arr.indexOf(2)) // 1
console.log(arr.indexOf(NaN)) // -1  indexOf不能检测NaN
console.log(NaN == NaN) // false
console.log(arr.includes(2)) // true
console.log(arr.includes(4)) // false
console.log(arr.includes(NaN)) // true

includes() 和 indexOf() 的区别:
includes() 和 index() 都是用于判断数组当中是否包含目标元素
indexOf() 判断目标元素时,如果存在返回索引,如果不存在返回-1,并且不能判断NaN
includes() 判断目标元素时,如果存在返回true,如果不存在返回false,并且能判断NaN

Array.prototype.copyWithin()

在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。
语法: arr.copyWithin(target, start = 0, end = this.length)
target从该位置开始替换数据。如果为负值,表示倒数
start从该位置开始读取数据,默认为 0。如果为负值,表示从末尾开始计算
end到该位置前停止读取数据,默认等于数组长度。如果为负值,表示从末尾开始计算

let arr = [1, 2, 3, 4, 5]
console.log(arr.copyWithin(1, 3))// [1, 4, 5, 4, 5]

如何判断一个变量是数组

  1. arr instanceof Array 返回true,说明变量arr是数组类型
  2. arr.constructor === Array 返回true,说明变量arr是数组类型
  3. Array.isArray(arr) 返回true,说明变量arr是数组类型
  4. Object.prototype.toString.call(arr) === '[object Array]' 返回true,则说明该变量是数组类型;反之,说明该变量不是数组类型
  5. arr.proto === Array.prototype 返回true,说明变量arr是数组类型
  6. Object.getPrototypeOf(arr) === Array.prototype 返回true,说明变量arr是数组类型
  7. Array.prototype.isPrototypeOf(arr) 返回true,说明变量arr是数组类型