api 进阶

forEach

arr.forEach(callback[, thisArg]);

callback

为数组中每个元素执行的函数,该函数接收三个参数:

currentValue

数组中正在处理的当前元素。

index可选

数组中正在处理的当前元素的索引。

array可选

forEach() 方法正在操作的数组。

thisArg可选

可选参数。当执行回调函数时用作 this 的值(参考对象)。

TIP

callback 方法可以使用箭头函数,不改变 this 指向。后两个不常用的参数,array 就是当前遍历的数组 (===),而最后的 thisArg可以改变当前对象。 但是一单使用箭头函数,第三个参数就会失效。

密集数组和稀疏数组

let arr1 = new Array(10)
// 并不会执行
arr1.forEach(item=>{
  console.log(item)
})

let arr2 = Array.apply(null, Array(10))
arr2.forEach(item=>{
  console.log(item)
})

TIP

创建数组,Array() 和 new Array() 是一样的。(Ecmascript 标准) When Array is called as a function rather than as a constructor, it creates and initialises a new Array object. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments.

forEach 会忽略稀疏数组中的空项(已删除或未初始化)。

跳出循环

forEach 不能跳出循环,除非抛出一个异常。

let arr = [{name:'a'},{name:'b'},{name:'c'},{name:'d'},{name:'e'}]
arr.forEach((item,index,a) => {
        if(item.name === 'a') return
        console.log(item)
      },new Object())

已访问的元素在迭代时被删除了

由于执行到 name === 'b' 时,第一项被删除了,这时候每一项会向上平移,在这之后的每一项输出当前的项就提前了一位。

arr.forEach((item,index,a) => {
        if(item.name === 'b') arr.shift()
        console.log(item);
      },new Object())
/*0: {name: "a"}
1: {name: "b"}
2: {name: "d"}
3: {name: "e"}*/

一些不解

forEach 遍历的范围在第一次调用 callback 前就会确定。调用 forEach 后添加到数组中的项不会被 callback 访问到。如果已经存在的值被改变, 则传递给 callback 的值是 forEach 遍历到他们那一刻的值。已删除的项不会被遍历到。

replace 的函数使用

String.prototype.replace

TIP

str.replace(regexp|substr, newSubStr|function)

当第二个参数传入一个函数时,函数会直接执行,函数的返回值会替换匹配到的结果。当第一个参数是正则表达式时,并且是全局匹配模式,那么函数会执行多次。 如果正则中含有括号匹配,那么相应的函数内会增加括号对应的参数,具体如下:

// 如果匹配模式是:
/(\a+)(\b+)/
replacer(match,p1,p2,ofsset,string)
// 其中 match 是匹配的字符串,p1 是第一个括号内的匹配,p2 ... offset 是子字符串在原字符串中的偏移量(也就是原来的 index 值),string
是原字符串。

选择器

Document​.query​SelectorAll