三.数组Array

Array

在ES6中新增了很多实用的API,方便开发者对Array的操控性更强,如for…of、from、of、find、findIndex等。


1. 数组遍历

关于数组的遍历,我们从最原始的for循环遍历数组到ES5遍历数组的API多了起来,其中forEach、every等来实现数组的遍历,到ES6则又加入了for…of API来遍历数组。

// 第一种.for循环
const arr = [1, 2, 3, 4, 5]
for (let i = 0; i < arr.length; i++) {
  if (arr[i] === 2) {
    break
  }
  console.log(arr[i])
}
// 第二种.foreach
arr.forEach(function (item) {
  console.log(item)
})

// 两种方法,
// 1.书写上看:forEach相对简单;
// 2.for语句中可以使用break、continue关键字,forEach中则会报错“语法不支持”

// 第三种.every
arr.every(function (item) {
  console.log(item)
  if (item === 2) {
    // return false 相当于 for循环中的break
    return false
  }
  if (item === 3) {
    // 相当于 for循环中的continue效果
  } else {
    console.log(item)
  }
  return true
})

// 要使数组全部返回,需要加return true;函数默认返回值为false;   受控制

// 第四个.for in 是为对象Object设置的 可以使用continue"两个=="才可有效果,因为本质是Object,index是字符串,两个==只检查值不检查类型
arr.a = 8
for (let index in arr) {
  // if (index == 2) {
  //   continue
  // }
  if (index * 1 === 2) {
    continue
  }
  console.log(index, arr[index])
}

// es6新增 for of   重点介绍:
for (variable of iterable) {
}
//这个伪代码,of 后面是 iterable 既不是 for 循环规定的 array,也不是 for…in 规定的 Object,而是 iterable。如果查查 iterable 的含义就很直观的感受到 for…of 遍历的是一切可遍历的元素(数组、对象、集合)等,不要小瞧这个功能,因为在 ES6 中允许开发者自定义遍历,换句话说任何数据结构都可以自定义一个遍历,这个遍历是不能被 for、for…in 理解和实现的。for…of是支持 break、continue的,所以在功能上非常贴近原生的 for.


// 自定义数据结构
const Price = {
  A: [1.5, 2.3, 4.5],
  B: [3, 4, 5],
  C: [0.5, 0.8, 1.2]
}
// 所得是一个数组,而for...of的得到的是1.5、3、0.5。
// A [1.5,2.3,4.5]这种
for (let key in Price) {
  console.log(key, Price[key])
}
for (let key of Price) {
  console.log(Price[key])
}


2. 伪数组转换数组

数组是开发中经常用到的数据结构,它非常好用。在 JavaScript 的世界里有些对象被理解为数组,然而缺不能使用数组的原生 API,比如函数中的 arguments、DOM中的 NodeList等。当然,还有一些可遍历的对象,看上去都像数组却不能直接使用数组的 API,因为它们是伪数组(Array-Like)。要想对这些对象使用数组的 API 就要想办法把它们转化为数组,传统的做法是这样的:

let args = [].slice.call(arguments);
let imgs = [].slice.call(document.querySelectorAll('img'));

基本原理是使用 call 将数组的 api 应用在新的对象上,换句话说是利用改变函数的上下文来间接使用数组的 api。
在 ES6 中提供了新的 api 来解决这个问题,就是 Array.from,代码如下:

let args = Array.from(arguments);
let imgs = Array.from(document.querySelectorAll('img'));
伪数组具有的两个特征:
  1. 按索引的方式存储。
  2. 具有Length属性。
    let arrLike = {
    0: ‘a’,
    1: ‘b’,
    2: ‘c’,
    length: 3
    }
语法:Array.from(arrayLike[, mapFn[, thisArg]])
参数 含义 必选
arrayLike 想要转换成数组的伪对象或可迭代对象 Y
mapFn 如果指定了该参数,新数组中的每个元素会执行该回调函数 N
thisArg 可选参数,执行回调函数mapFn时this对象 N

看了这几个参数至少能看到Array.from还具备map的功能,比如我们想初始化一个长度为5的数组,每个数组元素默认为 1,之前的做法是这样的:

let arr = Array(6).join(' ').split('').map(item=>1)
// [1,1,1,1,1]

而Array.from会相对简洁。

Array.from({ length: 5 }, function () { return 1 })
// 转换伪数组
 //ES5 的做法:
 let args = [].slice.call(arguments)  // collection
//arguments报错的原因: 1. 他只能在函数内使用;2. 他已经被ES6废弃,但ES5可以用
let imgs = [].slice.call(document.querySelectorAll('img')) // NodeList
 console.log(imgs)

// ES6做法
// Array.prototype.from  Array:数组对象;prototype:数组原型对象;from: 转换的api; from 新增api
 let args = Array.from(arguments)
 let imags = Array.from(document.querySelectorAll('img'))
 imags.forEach() // 已转换为数组,可以使用数组的api  foreach

// Array.from(arrayLike, mapFn, thisAry)

// 一个小case 定义一个长度为5的数组并赋值

 // 方法1: 只是通过遍历进行的赋值,不算纯粹的赋值,而且复杂
 let array = Array(5)
 for (let i = 0, len = array.length; i < len; i++) {
   array[i] = 1
 }
// 方法二:
let array = Array.from({ length: 5 }, function () { return 1 })
// {0: 'a', 1: 'b', length:2}
console.log(array)

思考

  1. 生成长度为5,为何用的是Array(6)

3. 生成新数组

Array.of(element0[, element1[, …[, elementN]]])
参数 含义 必选
element 任意个参数,将按顺序成为返回数组中的元素 Y

Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。
Array.of() 和 Array 构造函数之间的区别在于处理整数参数:
Array.of(7) 创建一个具有单个元素 7 的数组,而 Array(7) 创建一个长度为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.fill(value[, start[, end]])
参数 含义 必选
value 用来填充数组元素的值 Y
start 起始索引,默认值为0 N
end 终止默认值,默认值为this.length N

fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。

let array = [1, 2, 3, 4]
array.fill(0, 1, 2)
// [1,0,3,4]

fill 不具备遍历的功能,它是通过指定要操作的索引范围来进行,通过这道题目可以看出不指定索引会对所有元素进行操作

Array(5).fill(1)
// [1,1,1,1,1]

// 生成新数组
// ES5
// let array = Array(5)
// let array = ['']  push pop
// ES6
// Array.from
// Array.prototype.of 没有对数量的限制
let array = Array.of(1, 2, 3, 4, 5)
console.log(array)
// Array.prototype.fill 填充数组
let array2 = Array(5).fill(1)
console.log(array2)
// Array.fill(value, start, end)


4. 数组查找

arr.find(callback[, thisArg])
参数 含义 必选
callback 在数组每一项上执行的函数,接收3个参数,element、index、array Y
thisArg 执行回调时用作this的对象 N

find() 方法返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined。

let array = [5, 12, 8, 130, 44];
let found = array.find(function(element) {
return element > 10;
});
console.log(found);
// 12

arr.findIndex(callback[, thisArg])
参数 含义 必选
callback 在数组每一项上执行的函数,接收 3 个参数,element、index、array Y
thisArg 执行回调时用作 this 的对象 N

findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。其实这个和 find() 是成对的,不同的是它返回的是索引而不是值。

let array = [5, 12, 8, 130, 44];
let found = array.findIndex(function(element) {
return element > 10;
});
console.log(found);
// 1

思考

  1. find() 和 ES5 的 filter() 有什么区别?
  2. JavaScript 世界里有哪些元素是可遍历的?
  3. 如何给数据结构自定义遍历?

阅读:

  1. Array

你可能感兴趣的:(JavaScript,ES(6-10))