这是我参与更文挑战的第 29 天,活动详情查看 更文挑战
这个系列也没啥花头,就是来整平时面试的一些手写函数,考这些简单实现的好处是能看出基本编码水平,且占用时间不长,更全面地看出你的代码实力如何。一般不会出有很多边界条件的问题,那样面试时间不够用,考察不全面。
平时被考到的 api 如果不知道或不清楚,直接问面试官就行, api 怎么用这些 Google 下谁都能马上了解的知识也看不出水平。关键是在实现过程,和你的编码状态、习惯、思路清晰程度等。
注意是简单实现,不是完整实现,重要的是概念清晰和实现思路清晰,建议
先解释清除概念
=>写用例
=>写伪代码
=>再实现具体功能
,再优化
,一步步来。
21. Array.prototype.map()
是什么
map()
方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
测试用例
let arr = [1, 2, 3]
let test1 = arr.map(item => item * 2)
let test2 = arr.map((it, index) => {
return {
idx: index,
value: it
}
})
console.log(test1)
// [ 2, 4, 6 ]
console.log(test2)
// [ { idx: 0, value: 1 }, { idx: 1, value: 2 }, { idx: 2, value: 3 } ]
console.log(arr)
// [ 1, 2, 3 ] 原数组不变
语法
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
参数
callback
- 生成新数组元素的函数,使用三个参数:
currentValue
: callback 数组中正在处理的当前元素。index
可选: callback 数组中正在处理的当前元素的索引。array
可选: map 方法调用的数组。
- 生成新数组元素的函数,使用三个参数:
thisArg
可选- 执行 callback 函数时值被用作this。
返回值 一个由原数组每个元素执行回调函数的结果组成的新数组。
描述
-
map
方法会给原数组中的每个元素都按顺序调用一次callback
函数。callback 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。 callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。 -
因为map生成一个新数组,当你不打算使用返回的新数组却使用map是违背设计初衷的,请用
forEach或者for-of替代
。这两种情况你不该使用map:- 你不打算使用返回的新数组
- 你没有从回调函数中返回值。
-
callback 函数会被自动传入三个参数:
数组元素,元素索引,原数组本身
。 -
如果
thisArg
参数提供给map,则会被用作回调函数的this值。否则undefined会被用作回调函数的this值。 -
map 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)
-
map 方法处理数组元素的范围是在 callback 方法第一次调用之前就已经确定了。调用map方法之后追加的数组元素不会被callback访问。如果存在的数组元素改变了,那么传给callback的值是map访问该元素时的值。在map函数调用后但在访问该元素前,该元素被删除的话,则无法被访问到。
-
根据规范中定义的算法,如果被map调用的数组是离散的,新数组将也是离散的保持相同的索引为空。
简单手写实现
我们实现前总结下重点:
-
map
方法主要就是给原数组中的每个元素都按顺序调用一次callback
函数。并且把所有返回的结果组合在一起生成一个新的数组返回。 -
两个参数,必填项回调函数
callback
和 可选项thisArg
(callbackfn 函数执行时的 this 值)
测试用例就用上面的就行
Array.prototype.myMap = function(callbackfn, thisArg) {
// 平时后端一个数组一不小心返回了 null,你又没做好[]兜底,控制台的报错
if (this == null) {
throw new TypeError("Cannot read property 'map' of null or undefined");
}
// callbackfn 不是函数时抛出异常
if (typeof callbackfn !== 'function') {
throw new TypeError(callbackfn + ' is not a function')
}
// this 转成数组对象,有迭代器
let O = Object(this)
// 不影响原数组,新建一个数组
let newArr = new Array(O.length)
for (let k = 0; k < O.length; k++) {
// 检查 O 及其原型链是否包含属性 k
if (k in O) {
let currentValue = O[k]
// 传入 thisArg, 当前元素 currentValue, 索引 index(k), 原数组对象 array(O)
let mappedValue = callbackfn.call(thisArg, currentValue, k, O)
// 返回结果赋值给新数组
newArr[k] = mappedValue
}
}
return newArr
}
let arr = [1, 2, 3]
let test1 = arr.myMap(item => item * 2)
let test2 = arr.myMap((it, index) => {
return {
idx: index,
value: it
}
})
console.log(test1)
// [ 2, 4, 6 ]
console.log(test2)
// [ { idx: 0, value: 1 }, { idx: 1, value: 2 }, { idx: 2, value: 3 } ]
console.log(arr)
// [ 1, 2, 3 ]
22. Array.prototype.filter()
是什么
filter()
方法创建一个新数组, 其包含通过
所提供函数实现的测试
的所有元素
。 主要作用其实就是过滤。
// let arr = [1, 2, 3, 4, 5, 6]
// let test1 = arr.filter(item => item > 3)
// console.log(test1)
// // [ 4, 5, 6 ]
// console.log(arr)
// // [ 1, 2, 3, 4, 5, 6 ]
语法
var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
参数
callback
- 用来测试数组的每个元素的函数。返回
true
表示该元素通过测试,保留该元素,false
则不保留。它接受以下三个参数:element
: 数组中当前正在处理的元素。index
可选: 正在处理的元素在数组中的索引。array
可选: 调用了 filter 的数组本身。
- 用来测试数组的每个元素的函数。返回
thisArg
可选- 执行 callback 时,用于 this 的值。
返回值 一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。
描述
-
filter 为数组中的每个元素调用一次
callback
函数,并利用所有使得callback
返回true
或等价于true
的值的元素创建一个新数组。 -
callback 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过 callback 测试的元素会被跳过,不会被包含在新数组中。
-
callback 被调用时传入三个参数:
- 元素的值
- 元素的索引
- 被遍历的数组本身
-
如果为 filter 提供一个
thisArg
参数,则它会被作为 callback 被调用时的 this 值。 -
filter 不会改变原数组,它返回
过滤后的新数组
。 -
filter 遍历的元素范围在第一次调用 callback 之前就已经确定了。在调用 filter 之后被添加到数组中的元素不会被 filter 遍历到。如果已经存在的元素被改变了,则他们传入 callback 的值是 filter 遍历到它们那一刻的值。被删除或从来未被赋值的元素不会被遍历到。
简单手写实现
实现前总结下重点:
-
filter
方法主要作用就是过滤,他需要设置一个测试函数callback
,用来过滤数组中元素。留下所有测试函数返回 true 或等价于 true的元素。 -
两个参数,必填项用来测试数组的每个元素的函数
callback
和 可选项thisArg
(callback 函数执行时的 this 值)
实现倒不难,和 map 类似,看代码
Array.prototype.myFilter = function(callback, thisArg) {
// 上题有说明这里就略过
if (this == null) {
throw new TypeError("Cannot read property 'filter' of null or undefined");
}
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function')
}
let O = Object(this)
let newArr = new Array(O.length)
let to = 0
for (let k = 0; k < O.length; k++) {
if (k in O) {
let element = O[k]
// 就这边是不同,callback是个判断函数
if (callback.call(thisArg, element, k, O)) {
newArr[to++] = element;
}
}
}
newArr.length = to;
return newArr
}
let arr = [1, 2, 3, 4, 5, 6]
let test1 = arr.myFilter(item => item > 3)
console.log(test1)
// [ 4, 5, 6 ]
console.log(arr)
// [ 1, 2, 3, 4, 5, 6 ]
另外向大家着重推荐下另一个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列 记得点赞哈
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友
Or 搜索我的微信号infinity_9368
,可以聊天说地
加我暗号 "天王盖地虎" 下一句的英文
,验证消息请发给我
presious tower shock the rever monster
,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧