前言

很多方法之前都是用了就忘,记不住。有一个小技巧:通过整理归纳的方式,记忆会很深刻。而且,知道单词原来的意思,效果更好,比如splice,可以看下文中的翻译。

数组中改变原数组的方法

  1. arr.push(add1, add2...)
    用法:在数组末尾添加n个元素,返回数组长度
var arr = []
arr.push(1,2,3,4,true,{})
// [1,2,3,4,true,{}]
  1. arr.pop()
    用法:删除数组最后一个元素,并返回该元素。该方法没有参数
var arr = [1,2,3]
var item = arr.pop() // 3
  1. arr.shift()
    翻译为去掉
    用法:用于删除数组第一个元素,返回该元素。
var arr = [1,2,3]
var item = arr.shift() // 1
  1. arr.unshift(add1, add2...)
    用法:数组前面插入n个元素,返回数组长度。
var arr = []
var length = arr.unshift(1,2,3) // 3
  1. arr.reverse()
    翻译为翻转。
var arr = [1,2,3]
var newArr = arr.reverse() // [3,2,1]
  1. arr.sort(fn | 空)
    如果参数为空,默认先把数组中的元素转成字符串,按照字符串对应的unicode位排序。所以不要用sort来排序,就算数字也不行。
var arr = [10,101]
var newArr = arr.sort() // [101, 11]
var arr = arr.sort((a, b) => a - b) 

数组中不改变原数组的方法

  1. join('分隔符')
    翻译为连接,
    用法:表示用怎样的方式连接数组元素,返回一个字符串。默认参数为逗号
var arr = [1,2,3]
var str = arr.join() // '1,2,3'
  1. concat(arr | element1, element2...)
    翻译为合并数组。
    用法:参数为数组或其他类型都可以,如果是其他类型,那么会把这些元素插入到数组后面。返回一个合并后的数组。
var arr = [1,2,3]
var arr2 = [4,5,6]
var newArr = arr.concat(arr2) // [1,2,3,4,5,6]
newArr = arr.concat(7,8,9)
  1. arr.slice(start, end)
    翻译:把...分成部分。
    用法:返回一个数组,用于提取原数组中的部分。如果省略第二个参数。表示切割停止位置在数组末尾。如果参数为负数,那么代表倒数。默认参数为0,可以直接浅拷贝原数组。
var arr = [1,2,3]
newArr = arr.slice(-2, -1) // [2]
  1. arr.splice(start, count, add1, add2....)
    翻译:绳子捻接、胶片粘接。可以想像成一条胶带在某个位置切断一段,然后可以在断点处加上一段。
    返回值为一个数组,里面的元素是删除的元素。
var arr = [1,2,3]
newArr = arr.splice(0, 1, 4,5,6) // [4,5,6,2,3]
  1. map(fn, context)
    用法:参数两个,第一个为函数,第二个为this指向。返回一个数组。
var arr = [1,2,3]
var arr2 = [4,5,6]
var newArr = arr.map(function (item, idx) {
  return this[idx]
}, arr2)
  1. forEach(fn, context)
    用法:用法和map完全一样。返回一个数组。
    注意点:用法和map完全一样。注意在forEach中无法中断。

  2. filter(fn, context)
    用法:用法和forEach、map完全一样。返回一个数组。

  3. some(fn)、every(fn)
    用法:参数和map、forEach、filter一样。返回值为true/false

var arr = [1,2,3]
arr.some((item) => item > 2) // true

var arr = [1,2,3]
arr.every((item) => item > 2) // false
  1. reduce(fn)、reduceRight(fn)
var arr = [1,2,3]
arr.reduce((prev, cur, idx, arr) => {
  return prev - cur
}) // 1 - 2 - 3

var arr = [1,2,3]
arr.reduceRight((prev, cur) => {
  return prev - cur
}) // 3 - 2 - 1
  1. indexOf(ele, position)、lastIndexOf(ele, position)
    注意,第二个参数表示从第几个元素开始找。

  2. 返回值为数组的可以进行链式调用。

改变原数组方法(8)

traverse、push、pop、shift、unshift、sort、join、splice

没有改变原数组方法(11)

slice、map、forEach、filter、some、every、reduce、reduceRight、concat、indexOf、lastIndexOf

返回值为数组的方法

map、filter、splice、slice、concat、sort、reverse

数组查找元素的方法(6)

[1,2,3].some(x => x === 1) // true 找到该元素就不再循环,
[1,2,3].filter(x => x === 1).length //[1] 判断数组长度是否大于0
[1,2,3].find(x => x === 1) // true
[6,2,3].findIndex(x => x === 6) // 0 返回索引
[1,2,3].includes(1) //true
[6,2,3].indexOf(6) // 0 返回索引

忘记点

不改变原数组的:concat

reduce

先看redux中的compose函数实现

function compose(...funcs) {
      if (funcs.length === 0) {
        return arg => arg
      }

      if (funcs.length === 1) {
        return funcs[0]
      }
      return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

用法

    function fn1(x) {
      console.log('a')
      return x + 1
    }

    function fn2(x) {
      console.log('b')
      return x + 2
    }

    function fn3(x) {
      console.log('c')
      return x + 3
    }

    function fn4(x) {
      console.log('d')
      return x + 4
    }

    let composedFn = compose(fn1,fn2,fn3,fn4)
    let result = composedFn(1)
    console.log(result)

解析

// 第一次:a:fn1, b:fn2,也就是fn2执行了,将函数返回值传给fn1
// 第二次:a: (...args) => { return fn1(fn2(...args)) }, b: fn3, 现在我将前面这个函数叫做x
// 第三次:a: (...args) => x(fn3(...args)), b: fn4,现在我将前面这个函数叫做y,也就是返回(...args) => {return y(fn4(...args))},赋值到composedFn上
// 现在执行composedFn,流程就很清楚了。
function compose(...funcs) {
     if (funcs.length === 0) {
       return arg => arg
     }

     if (funcs.length === 1) {
       return funcs[0]
     }
     return funcs.reduce((a, b) => {
       return (...args) => { // 这个args用来获取前一次函数执行的返回值
         return a(b(...args)) // 这个args用来获取第一次传进来的参数
       }
     })
   }

自己实现compose

    function compose2(...funcs) {
      if (funcs.length === 0) {
        return arg => arg
      }

      if (funcs.length === 1) {
        return funcs[0]
      }

     return (...args) => {
        const lastFn = funcs.pop()
        return funcs.reduceRight((a, b) => { // a就是每次的返回值,b就是从后到前每个函数
          return b(a)
        }, lastFn(...args))
     }
    }
    let composedFn2 = compose2(fn1,fn2,fn3,fn4)
    let result2 = composedFn2(1)
    console.log(result2)

     // 用箭头函数不直观
    function compose3(...funcs) {
      if (funcs.length === 0) {
        return arg => arg
      }

      if (funcs.length === 1) {
        return funcs[0]
      }

      return (...args) => funcs.reduceRight((a, b) => b(a), funcs.pop()(...args))
    }

reduce实现

    Array.prototype.reduce = function (fn, prev) {
      const len = this.length
      const argLen = arguments.length
      if (len === 0) {
        throw new TypeError('Reduce of empty array with no initial value')
      }
      if (len === 1 && argLen < 2) {
        return this[0]
      }

      for (let i = 0; i < len; ++i) {
        if (i === 0) {
          if (argLen > 1) {
            prev = fn(prev, this[i], i, this)
          } else {
            prev = fn(this[i], this[i+1], i+1, this)
          }
        } else {
          prev = fn(prev, this[i+1], i+1, this)
        }

        if (len === 1) { // 当前数组只有一个元素,并且传了初始值的情况
          return prev
        }
        if (i === len - 2) {
          return prev
        }
      }
    };
    let result = [].reduce((a, b, i, arr) => {
      console.log(a,b,i)
      return a + b
    })
    console.log(result)

上面的实现有以下几个注意点:

  1. 考虑数组长度为0的情况
  2. 考虑当前数组长度为1,但是有第二个参数的情况
  3. 考虑首次执行时,有无第二个参数的情况