前言

尽管有时候遍历数组只须要 for 循环则足矣,然而如果 API 利用切当,往往能更大程度的进步代码的可读性,缩小心智累赘~

常见的数组 API

Array.prototype.some

性能

判断数组中是否至多有一个项通过了预设的条件,后果返回 boolean

参数

  • callback:执行的回调函数,用于条件判断。
  • thisArg:执行函数的 this 指针。

场景

判断数组 [ 1, 2, 3, 5, 6, 7 ] 中是否存在偶数

const target = [ 1, 2, 3, 5, 6, 7 ]if (target.some(a => a % 2 === 0)) {    // do something   }

Polyfill

Array.prototype.some = function(fn, thisArg) {    // 异样解决    if (this == null) {        throw new TypeError('Cannot read property of null or undefined.')    }    if (typeof fn !== 'function') {        throw new TypeError(`${fn} must be a function.`)    }    // 须要用 Object 包装一次 this    const O = Object(this)    const len = O.length || 0    for (let i = 0; i < len; i++) {        if (i in O) {            if (fn.call(thisArg, O[i], i, O)) {                return true            }        }    }    return false}

Array.prototype.every

性能

判断数组中是否全副项都通过了预设的条件,后果返回 boolean

参数

  • callback:执行的回调函数,用于条件判断。
  • thisArg:执行函数的 this 指针。

场景

判断数组 [ 1, 2, 3, 5, 6, 7 ] 是否每个数都是偶数。

const target = [ 1, 2, 3, 5, 6, 7 ]if (target.every((num) => num % 2 === 0)) {  // do something}

Polyfill

Array.prototype.every = function(fn, thisArg) {  // 异样解决  if (this == null) {    throw TypeError('Cannot read property of null or undefined')  }  if (typeof fn !== 'function') {    throw TypeError(`${fn} is not a function`)  }  // 从新包装一次 this  const O = Object(this)  const len = O.length || 0  for (let i = 0; i < len; i++) {    if (i in O) {      if (!fn.call(thisArg, O[i], i, O)) {        return false      }       }  }  return true}

Array.prototype.slice

性能

浅拷贝数组,能够指定开始和完结下标来对数组某段做拷贝。如果不增加任何参数,那么会间接拷贝整个数组。

参数

  • begin(可选参数): 从这个下标开始拷贝,如果为正数,则示意从倒数第 begin 开始拷贝。
  • end(可选参数): 从这个下标完结拷贝,如果为正数,则示意从倒数第 end 完结拷贝。

场景

拷贝数组 [ 1, 2, 3, 5, 6, 7 ] 到另外一个数组。

const target = [ 1, 2, 3, 5, 6, 7 ]const temp = target.slice()

Polyfill

Array.prototype.slice = function(begin, end) {      if (this == null) {          throw new TypeError('cannot read property of null or undefined')      }            // 如果 end 没有传就默认截到数组开端      end = (typeof end !== 'undefined') ? end : this.length      const cloned = []      const len = this.length      let i = 0      // 解决下 begin 参数      let start = begin || 0      start = (start >= 0) ? start : Math.max(0, len + start)      let upTo = (typeof end == 'number') ? Math.min(end, len) : len      if (end < 0) {        upTo = len + end      }          // 计算 upTo 到 start 之间的差值      let size = upTo - start          // 如果 size > 0 就计算      // 再拷贝到 cloned 数组中      if (size > 0) {        for (i = 0; i < size; i++) {          cloned[i] = this[start + i]        }      }      return cloned    };

Array.prototype.reduce

性能

对数组中的每个元素执行一个由您提供的reducer函数,将其后果汇总为单个返回值。

参数

  • callback

    • accumulator
    • currValue
    • index
    • array(调用 reduce 的数组)
  • initValue

场景

计算数组 [ 1, 2, 3, 5, 6, 7 ] 的和。

const target = [ 1, 2, 3, 5, 6, 7 ]const sum = target.reduce((prev, curr) => prev + curr)

Polyfill

Array.prototype.reduce = function(fn, initValue) {    // 异样判断    if (this == null) {        throw new TypeError('Cannot read property of null or undefined')    }    if (typeof fn !== 'function') {        throw new TypeError(`${fn} must be a function`)    }    const O = Object(this)    const len = O.length || 0    let i = 0    let k = 0    let accumulator = initValue    // 遍历并拿到后果    while (i < len) {        if (i in O) {            if (!accumulator) {                accumulator = O[i]            } else {                accumulator = fn.call(this, accumulator, O[i], i, O)            }        } else {            k++        }        i++    }    // 空数组异样判断    if (k >= len) {        throw new TypeError('Reduce of empty array with no initial value')    }    return accumulator}

Array.prototype.map

性能

创立一个新数组,其后果是该数组中的每个元素调用一次提供的函数后的返回值。

参数

  • callback

    • currentValue
    • index
    • array
  • thisArg

场景

将数组 [ 1, 2, 3, 5, 6, 7 ] 转化成对象数组,格局为 [{val: 1}, ...]

const target = [ 1, 2, 3, 5, 6, 7 ]const objArr = target.map((num) => {    return {        val: num    }})

Polyfill

Array.prototype.map = function(fn, thisArg) {    // 异样判断    if (this == null) {        throw new TypeError('Cannot read property of null or undefined.')    }    if (typeof fn !== 'function') {        throw new TypeError(`${fn} is not a function.`)    }    const O = Object(this)    const len = O.length || 0    const res = []    // 遍历并拿到后果    for (let i = 0; i < len; i++) {        if (i in O) {            res.push(fn.call(thisArg, O[i], i, O))        }    }    return res}

总结

看完下面这些 Polyfill 之后,咱们能够找到一些法则,以便遇到没见过的 Polyfill 也能写出个大略:

  • this 指针和传入的回调函数做异样判断
  • thisObject 从新包装一层
  • 具体的逻辑解决,每个函数都不太一样
  • 返回后果

参考资料

  • MDN

搜寻「tony老师的前端补习班」关注我的微信公众号,那么就能够第一工夫收到我的最新文章。