作为大龄失业青年,在这个就业率低的时代,我也很无奈。
但是!!!!
八股文,该背还得背
那么
对于面试中的遇到的,手写数组的方法,比如 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
}
自此,我们的手写就完成了。