如何快速记住手写数组方法的那些代码

作为大龄失业青年,在这个就业率低的时代,我也很无奈。

但是!!!!

八股文,该背还得背

那么

对于面试中的遇到的,手写数组的方法,比如 Array.forEach、Array.map、Array.filter、Array.reduce、Array.push、Array.pop

怎么能快速进行呢

特别提示⚠️:小菜鸟自嗨中,大佬可以麻烦退出,不浪费时间

Array.prototype.forEach()

为什么要先说 forEach,因为 forEach 是可以为后续的 Array.map、Array.filter、Array.reduce 搭建基础框架的。后续的三个代码都是在 forEach 上缝缝补补的


forEach 的使用

js 复制代码
[1, 2, 3, 4, 5, 6].forEach((item) => {
  console.log('item', item)
})

首先,我们需要做一些异常判断

js 复制代码
Array.prototype.forEach = function (callback, thisArg) {
  if (this === undefined) {
    throw new Error('error')
  }
  if (typeof callback !== "function") {
    throw new Error("error")
  }
}

之后,对于数组的遍历,需要用到for 循环

对,

就是那个原始的 for 循环

js 复制代码
Array.prototype.forEach = function (callback, thisArg) {
  if (this === undefined) {
    throw new Error('error')
  }
  if (typeof callback !== "function") {
    throw new Error("error")
  }
  const O = Object(this)
  const len = O.length >>> 0
  for (let i = 0; i < len; i++) {
    // ...
  }
}

O 就是需要处理的对象,即这里的数组

接下来需要判断,当前这个元素,是不是在获取的对象上。如果是,那就用传入的回调函数去进行处理即可。

js 复制代码
Array.prototype.forEach = function (callback, thisArg) {
  if (this === undefined) {
    throw new Error('error')
  }
  if (typeof callback !== "function") {
    throw new Error("error")
  }
  const O = Object(this)
  const len = O.length >>> 0
  for (let i = 0; i < len; i++) {
    if (i in O) {
      callback.call(thisArg, O[i], i, O)
    }
  }
}

Array.prototype.map()

map 的使用

js 复制代码
const result = [1, 2, 3, 4, 5, 6].map((item) => item * 2)

按照我们之前说的,我们需要用到 forEach 的手写代码,改个名字

js 复制代码
Array.prototype.map = function (callback, thisArg) {
  if (this === undefined) {
    throw new Error('error')
  }
  if (typeof callback !== "function") {
    throw new Error("error")
  }
  const O = Object(this)
  const len = O.length >>> 0
  for (let i = 0; i < len; i++) {
    if (i in O) {
      callback.call(thisArg, O[i], i, O)
    }
  }
}

map 需要返回一个新数组,所以我们需要定义一个新数组,这个数组的长度和传入的数组长度一致。

js 复制代码
let result = new Array(len)

return result

新数组的数据,就是对原数组的数据进行处理

js 复制代码
result[i] = callback.call(thisArg, O[i], i, O)

好的,就多了这么三行代码,是的,组合一下

js 复制代码
Array.prototype.map = function (callback, thisArg) {
  if (this === undefined) {
    throw new Error('error')
  }
  if (typeof callback !== "function") {
    throw new Error("error")
  }
  const O = Object(this)
  const len = O.length >>> 0
  let result = new Array(len)
  for (let i = 0; i < len; i++) {
    if (i in O) {
      result[i] = callback.call(thisArg, O[i], i, O)
    }
  }
  return result
}

Array.prototype.filter()

filter 的使用

js 复制代码
const result = [1, 2, 3, 4, 5, 6].filter((item) => item > 2)

框架抄下来,改个名字

js 复制代码
Array.prototype.filter = function (callback, thisArg) {
  if (this === undefined) {
    throw new Error('error')
  }
  if (typeof callback !== "function") {
    throw new Error("error")
  }
  const O = Object(this)
  const len = O.length >>> 0
  for (let i = 0; i < len; i++) {
    if (i in O) {
      callback.call(thisArg, O[i], i, O)
    }
  }
}

map 需要返回一个新数组,所以我们需要定义一个新数组。同时,我们还需要定义一个变量 resLen。

js 复制代码
let result = []
let resLen = 0

return result

filter 对于满足回掉的数组,才会返回,这里就需要在 for 循环中进行判断,是否符合,符合的情况下才会放入新数组中。

js 复制代码
if (i in O) {
  if (callback.call(thisArg, O[i], i, O)) {
     result[resLen++] = O[i]
  }
}

好的,五行代码,组合一下

js 复制代码
Array.prototype.filter = function (callback, thisArg) {
  if (this === undefined) {
    throw new Error('error')
  }
  if (typeof callback !== "function") {
    throw new Error("error")
  }
  const O = Object(this)
  const len = O.length >>> 0
  let result = []
  let resLen = 0
  for (let i = 0; i < len; i++) {
    if (i in O) {
      if (callback.call(thisArg, O[i], i, O)) {
        result[resLen++] = O[i]
      }
    }
  }
  return result
}

Array.prototype.reduce()

reduce 的使用

js 复制代码
const result = [1, 2, 3, 4, 5, 6].reduce((cur, pre) => {
  return cur + pre
}, 100)

框架抄下来,改个名字,这里有一个改动,我们需要传入 initValue

js 复制代码
Array.prototype.reduce = function (callback, initValue) {
  if (this === undefined) {
    throw new Error('error')
  }
  if (typeof callback !== "function") {
    throw new Error("error")
  }
  const O = Object(this)
  const len = O.length >>> 0
  for (let i = 0; i < len; i++) {
    if (i in O) {
      callback.call(thisArg, O[i], i, O)
    }
  }
}

默认返回初始值,因此 result === initValue

js 复制代码
let result = initValue

return result

当不提供初始值的时候,就取数组的第一个

js 复制代码
let i = 0;
if (initValue === undefined) {
  for (; i < len; i++) {
    if (i in O) {
      result = O[i];
      i++;
      break;
    }
  }
}

之后,按照正常的 for 循环,对 result 数组进行赋值

js 复制代码
for (; i < len; i++) {
  if (i in O) {
    result = callback.call(undefined, result, O[i], i, O);
  }
}

好的,对代码进行组装

js 复制代码
Array.prototype.reduce = function (callback, initValue) {
  if (this === undefined) {
    throw new Error('error')
  }
  if (typeof callback !== "function") {
    throw new Error("error")
  }
  const O = Object(this)
  const len = O.length >>> 0
  let result = initValue
  let i = 0
  if (initValue === undefined) {
    for (; i < len; i++) {
      if (i in O) {
        result = O[i]
        i++
        break
      }
    }
  }
  for (; i < len; i++) {
    if (i in O) {
      result = callback.call(undefined, result, O[i], i, O)
    }
  }
  return result
}

下面两个,前面的 forEach 框架就不能用了

Array.prototype.push()

push 是返回新数组的长度,所以我们需要定义一个 newLength 用来作为新数组的长度。新数组的长度,当然是等于原来的长度+新传入的数据的长度。还需要做一些判断,比如,有一个非常非常非常非常长的数组,已经大于 2 ** 53 - 1。这个时候,就需要报错了。

js 复制代码
Array.prototype.push = function (...items) {
  const O = Object(this)
  const len = O.length >>> 0
  const argCount = items.length >>> 0
  if (len + argCount > 2 ** 53 - 1) {
    throw new Error("error")
  }
  let newLength = len + argCount
  O.length = newLength
  return newLength
}

当然,这只是长度的处理,还需要把新数据放入原数组中。

js 复制代码
for (let i = 0; i < argCount; i++) {
  O[len + i] = items[i]
}

组合一下

js 复制代码
Array.prototype.push = function (...items) {
  const O = Object(this)
  const len = O.length >>> 0
  const argCount = items.length >>> 0
  if (len + argCount > 2 ** 53 - 1) {
    throw new Error("error")
  }
  let newLength = len + argCount
  O.length = newLength
  for (let i = 0; i < argCount; i++) {
    O[len + i] = items[i]
  }
  return newLength
}

Array.prototype.pop()

pop 会删除数组的最后一项,并且返回删除的该项。如果长度为空,则会返回 undefined。

js 复制代码
Array.prototype.pop = function () {
  const O = Object(this)
  let len = O.length >>> 0
  if (len === 0) {
    O.length = 0
    return undefined
  }
  len--
  let result = O[len]
  delete O[len]
  O.length = len
  return result
}

自此,我们的手写就完成了。

相关推荐
前端Hardy23 分钟前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu108301891126 分钟前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
小镇程序员3 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
疯狂的沙粒4 小时前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪4 小时前
AJAX的基本使用
前端·javascript·ajax
力透键背4 小时前
display: none和visibility: hidden的区别
开发语言·前端·javascript
程楠楠&M4 小时前
node.js第三方Express 框架
前端·javascript·node.js·express
weiabc4 小时前
学习electron
javascript·学习·electron
想自律的露西西★4 小时前
用el-scrollbar实现滚动条,拖动滚动条可以滚动,但是通过鼠标滑轮却无效
前端·javascript·css·vue.js·elementui·前端框架·html5
白墨阳5 小时前
vue3:瀑布流
前端·javascript·vue.js