2024年前端最新【JS必知必会】高阶函数详解与实战,2024年最新2024疫情期间八家大厂的Web前端面试经历和真题整理

最后

今天的文章可谓是积蓄了我这几年来的应聘和面试经历总结出来的经验,干货满满呀!如果你能够一直坚持看到这儿,那么首先我还是十分佩服你的毅力的。不过光是看完而不去付出行动,或者直接进入你的收藏夹里吃灰,那么我写这篇文章就没多大意义了。所以看完之后,还是多多行动起来吧!

可以非常负责地说,如果你能够坚持把我上面列举的内容都一个不拉地看完并且全部消化为自己的知识的话,那么你就至少已经达到了中级开发工程师以上的水平,进入大厂技术这块是基本没有什么问题的了。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

// [1, 2, 3, 4]

map高阶函数注意点

callback需要有return值,否则会出现所有项映射为undefind;

// kaola

const arr1 = [1, 2, 3, 4];

const arr2 = arr1.map(item => {});

console.log( arr2 );

// [ undefined, undefined, undefined, undefined ]

console.log( arr1 );

// [1, 2, 3, 4]

map高阶函数对应的一道经典面试题

//输出结果

[“1”, “2”, “3”].map(parseInt);

看了这道题不知道会不会有大多数开发者认为输出结果是[1,2,3],错误

正确的输出结果为:

[1,NaN,NaN]

分析与讲解

因为mapcallback函数有三个参数,正在遍历的元素, 元素索引(index), 原数组本身(array)。parseInt有两个参数,string和radix(进制),注意第二个参数进制当为0或者没有参数的时候,parseInt()会根据string来判断数字的基数。当忽略参数 radix , js 默认数字的基数如下:

  • 如果 string 以 “0x” 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。

  • 如果 string 以 0 开头,那么 ECMAScript v3 允许 parseInt() 的一个实现把其后的字符解析为八进制或十六进制的数字。

  • 如果 string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数。

只传入parseInt的话,map callback会自动忽略第三个参数array。而index参数不会被忽略。而不被忽略的index(0,1,2)就会被parseInt当做第二个参数。

将其拆开看:

parseInt(“1”,0);//上面说过第二个参数为进制,所以"1",radix为0上面提到过,会忽略,根据string 以 1 ~ 9 的数字开头,parseInt() 将把它解析为十进制的整数1。

parseInt(“2”,1);//此时将2转为1进制数,由于超过进制数1,所以返回NaN。

parseInt(“3”,2);//此时将3转为2进制数,由于超过进制数1,所以返回NaN。

所以最终的结果为[1,NaN,NaN]

那么如果想要得到[1,2,3]该怎么写。

[“1”,“2”,“3”].map((x)=>{

return parseInt(x);

});

也可以简写为: ["1","2","3"].map(x=>parseInt(x));

这样写为什么就能返回想要的值呢?因为,传一个完整函数进去,有形参,有返回值。这样就不会造成因为参数传入错误而造成结果错误了,最后返回一个经纯函数处理过的新数组。

Array.prototype.reduce


reduce() 方法对数组中的每个元素执行一个提供的 reducer 函数(升序执行),将其结果汇总为单个返回值。传递给 reduce 的回调函数(callback)接受四个参数,分别是累加器 accumulatorcurrentValue——正在操作的元素、currentIndex(可选)——元素索引,但是它的开始会有特殊说明、array(可选)——原始数组本身,除了 callback 之外还可以接受初始值 initialValue 值(可选)。

  • 如果没有提供 initialValue,那么第一次调用 callback 函数时,accumulator 使用原数组中的第一个元素,currentValue 即是数组中的第二个元素。 在没有初始值的空数组上调用 reduce 将报错。

  • 如果提供了 initialValue,那么将作为第一次调用 callback 函数时的第一个参数的值,即 accumulator,currentValue 使用原数组中的第一个元素。

例子,现在有一个数组 [0, 1, 2, 3, 4],需要计算数组元素的和,需求比较简单,来看下代码实现。

不使用高阶函数

//koala

const arr = [0, 1, 2, 3, 4];

let sum = 0;

for (let i = 0; i < arr.length; i++) {

sum += arr[i];

}

console.log( sum );

// 10

console.log( arr );

// [0, 1, 2, 3, 4]

复制代码

使用高阶函数

无 initialValue 值

const arr = [0, 1, 2, 3, 4];

let sum = arr.reduce((accumulator, currentValue, currentIndex, array) => {

return accumulator + currentValue;

});

console.log( sum );

// 10

console.log( arr );

// [0, 1, 2, 3, 4]

复制代码

上面是没有 initialValue 的情况,代码的执行过程如下,callback 总共调用四次。

| callback | accumulator | currentValue | currentIndex | array | return value |

| — | — | — | — | — | — |

| first call | 0 | 1 | 1 | [0, 1, 2, 3, 4] | 1 |

| second call | 1 | 2 | 2 | [0, 1, 2, 3, 4] | 3 |

| third call | 3 | 3 | 3 | [0, 1, 2, 3, 4] | 6 |

| fourth call | 6 | 4 | 4 | [0, 1, 2, 3, 4] | 10 |

有 initialValue 值

我们再来看下有 initialValue 的情况,假设 initialValue 值为 10,我们看下代码。

//koala

const arr = [0, 1, 2, 3, 4];

let sum = arr.reduce((accumulator, currentValue, currentIndex, array) => {

return accumulator + currentValue;

}, 10);

console.log( sum );

// 20

console.log( arr );

// [0, 1, 2, 3, 4]

复制代码

代码的执行过程如下所示,callback 总共调用五次。

| callback | accumulator | currentValue | currentIndex | array | return value |

| — | — | — | — | — | — |

| first call | 10 | 0 | 0 | [0, 1, 2, 3, 4] | 10 |

| second call | 10 | 1 | 1 | [0, 1, 2, 3, 4] | 11 |

| third call | 11 | 2 | 2 | [0, 1, 2, 3, 4] | 13 |

| fourth call | 13 | 3 | 3 | [0, 1, 2, 3, 4] | 16 |

| fifth call | 16 | 4 | 4 | [0, 1, 2, 3, 4] | 20 |

Array.prototype.filter


filter(过滤,筛选) 方法创建一个新数组,原始数组不发生改变。

array.filter(callback,[ thisObject]);

其包含通过提供函数实现的测试的所有元素。接收的参数和 map 是一样的,filter的callback函数需要返回布尔值true或false. 如果为true则表示通过啦!如果为false则失败,其返回值是一个新数组,由通过测试为true的所有元素组成,如果没有任何数组元素通过测试,则返回空数组。

来个例子介绍下,现在有一个数组 [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4],我们想要生成一个新数组,这个数组要求没有重复的内容,即为去重。

不使用高阶函数

const arr1 = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];

const arr2 = [];

for (let i = 0; i < arr1.length; i++) {

if (arr1.indexOf( arr1[i] ) === i) {

arr2.push( arr1[i] );

}

}

console.log( arr2 );

// [1, 2, 3, 5, 4]

console.log( arr1 );

// [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4]

使用高阶函数

const arr1 = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];

const arr2 = arr1.filter( (element, index, self) => {

return self.indexOf( element ) === index;

});

console.log( arr2 );

// [1, 2, 3, 5, 4]

console.log( arr1 );

// [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4]

filter注意点说明

callback在过滤测试的时候,一定要是Boolean值吗? 例子:

var arr = [0, 1, 2, 3];

var arrayFilter = arr.filter(function(item) {

return item;

});

console.log(arrayFilter); // [1, 2, 3]

通过例子可以看出:过滤测试的返回值只要是弱等于== true/false就可以了,而非非得返回 === true/false.

Array.prototype.sort


sort()方法用原地算法对数组的元素进行排序,并返回数组,该排序方法会在原数组上直接进行排序,并不会生成一个排好序的新数组。排序算法现在是稳定的。默认排序顺序是根据字符串Unicode码点。

// 语法

arr.sort([compareFunction])

compareFunction参数是可选的,用来指定按某种顺序进行排列的函数。注意该函数有两个参数:

参数1:firstEl

第一个用于比较的元素。

参数2:secondEl

第二个用于比较的元素。看下面的例子与说明:

// 未指明compareFunction函数

[‘Google’, ‘Apple’, ‘Microsoft’].sort(); // [‘Apple’, ‘Google’, ‘Microsoft’];

// apple排在了最后:

[‘Google’, ‘apple’, ‘Microsoft’].sort(); // [‘Google’, 'Microsoft", ‘apple’]

// 无法理解的结果:

[10, 20, 1, 2].sort(); // [1, 10, 2, 20]

//正确的结果

[6, 8, 1, 2].sort(); // [1, 2,6, 8]

// 指明compareFunction函数

‘use strict’;

var arr = [10, 20, 1, 2];

arr.sort(function (x, y) {

if (x < y) {

return -1;

}

if (x > y) {

return 1;

}

return 0;

});

console.log(arr); // [1, 2, 10, 20]

如果没有指明 compareFunction ,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。例如 “Banana” 会被排列到 “cherry” 之前。当数字按由小到大排序时,10 出现在 2 之前,但因为(没有指明 compareFunction),比较的数字会先被转换为字符串,所以在Unicode顺序上 “10” 要比 “2” 要靠前。

如果指明了 compareFunction ,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:

  • 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;

  • 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);

  • 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。

compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。

sort排序算法的底层实现

看了上面sort的排序介绍,我想小伙伴们肯定会对sort排序算法的内部实现感兴趣,我在sf上面搜了一下,发现有些争议。于是去查看了V8引擎的源码,发现在源码中的710行

源码地址:github.com/v8/v8/blob/…

// In-place QuickSort algorithm.

// For short (length <= 22) arrays, insertion sort is used for efficiency.

V8 引擎 sort 函数只给出了两种排序 InsertionSortQuickSort数量小于等于22的数组使用 InsertionSort,比22大的数组则使用 QuickSort,有兴趣的可以看看具体算法实现。

最后

前端CSS面试题文档,JavaScript面试题文档,Vue面试题文档,大厂面试题文档

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

于是去查看了V8引擎的源码,发现在源码中的710行

源码地址:github.com/v8/v8/blob/…

// In-place QuickSort algorithm.

// For short (length <= 22) arrays, insertion sort is used for efficiency.

V8 引擎 sort 函数只给出了两种排序 InsertionSortQuickSort数量小于等于22的数组使用 InsertionSort,比22大的数组则使用 QuickSort,有兴趣的可以看看具体算法实现。

最后

前端CSS面试题文档,JavaScript面试题文档,Vue面试题文档,大厂面试题文档

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

[外链图片转存中…(img-Tx0HFAzY-1715601971132)]

[外链图片转存中…(img-4nO92W8b-1715601971133)]

  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值