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

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

但是!!!!

八股文,该背还得背

那么

对于面试中的遇到的,手写数组的方法,比如 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
}

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

相关推荐
RickeyBoy3 小时前
SwiftUI 如何实现 Infinite Scroll?
ios·面试
跟着珅聪学java6 小时前
js编写中文转unicode 教程
前端·javascript·数据库
英俊潇洒美少年6 小时前
Vue3 深入响应式系统
前端·javascript·vue.js
颜酱6 小时前
回溯算法实战练习(3)
javascript·后端·算法
前端摸鱼匠6 小时前
【AI大模型春招面试题12】Scaling Laws揭示了模型性能、数据量、计算量之间的什么关系?
人工智能·ai·语言模型·面试·大模型
我命由我123457 小时前
React Router 6 - 概述、基础路由、重定向、NavLink、路由表
前端·javascript·react.js·前端框架·ecmascript·html5·js
yaaakaaang8 小时前
(四)前端,如此简单!---Promise
前端·javascript
aini_lovee8 小时前
C# 实现邮件发送源码(支持附件)
开发语言·javascript·c#
英俊潇洒美少年8 小时前
js 进程与线程的讲解
javascript
敲代码的嘎仔9 小时前
Java后端开发——真实面试汇总(持续更新)
java·开发语言·程序人生·面试·职场和发展·八股