关于前端:盘点那些常见的-JS-数组方法及-Polyfill

43次阅读

共计 3310 个字符,预计需要花费 9 分钟才能阅读完成。

前言

尽管有时候遍历数组只须要 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 老师的前端补习班」关注我的微信公众号,那么就能够第一工夫收到我的最新文章。

正文完
 0