当前位置 博文首页 > LuckyWinty的博客:十道大厂面试题(含答案)总结

    LuckyWinty的博客:十道大厂面试题(含答案)总结

    作者:[db:作者] 时间:2021-06-13 15:37

    又到了跳槽季啦,该刷题走起了。这里总结了一些被问到可能会懵逼的面试真题,有需要的可以看下~

    PS:点击阅读原文即可进入前端Q题库,每周N题,来刷题吧~

    1.不借助变量,交换两个数

    1. 算术交换

    针对的是Number,或者类型可以转换成数字的变量类型

    function?swap(a,?b)?{
    ???a?=?a?+?b;
    ???b?=?a?-?b;
    ???a?=?a?-?b;
    }
    

    通过算术运算过程中的技巧,可以巧妙地将两个值进行互换。但是,有个缺点就是变量数据溢出。因为JavaScript能存储数字的精度范围是 -2^53 到 2^53。所以,加法运算,会存在溢出的问题。

    2. 异或运算

    ^ 按位异或 若参加运算的两个二进制位值相同则为0,否则为1 此算法能够实现是由异或运算的特点决定的,通过异或运算能够使数据中的某些位翻转,其他位不变。这就意味着任意一个数与任意一个给定的值连续异或两次,值不变.

    a?=?a?^?b;
    b?=?a?^?b;?
    a?=?a?^?b;
    

    3. ES6的解构

    [a,?b]?=?[b,?a];
    

    更多参考:

    • https://juejin.im/post/58b42fcc5c497d006793cd04

    • https://www.jianshu.com/p/61370227d096

    2.实现sum(1,2,3)==sum(1)(2)(3)

    function?sum(...args){
    ??function?currySum(...rest){
    ????args.push(...rest)
    ????return?currySum
    ??}
    ??currySum.toString=?function(){?
    ????return?args.reduce((result,cur)=>{
    ??????return?result?+?cur
    ????})
    ??}
    ??currySum.toNumber=?function(){?
    ????return?args.reduce((result,cur)=>{
    ??????return?result?+?cur
    ????})
    ??}
    ??return?currySum
    }
    

    更多参考:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/134

    3.观察者模式 vs 发布-订阅模式,说说区别

    观察者模式的概念

    观察者模式模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主体对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

    发布订阅者模式的概念

    发布-订阅模式,消息的发送方,叫做发布者(publishers),消息不会直接发送给特定的接收者,叫做订阅者。意思就是发布者和订阅者不知道对方的存在。需要一个第三方组件,叫做信息中介,它将订阅者和发布者串联起来,它过滤和分配所有输入的消息。换句话说,发布-订阅模式用来处理不同系统组件的信息交流,即使这些组件不知道对方的存在。

    区别

    我们把这些差异快速总结一下:

    在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。

    在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。

    观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)。

    观察者 模式需要在单个应用程序地址空间中实现,而发布-订阅更像交叉应用模式。

    更多:https://juejin.im/post/5a14e9edf265da4312808d86?

    PS:最好把对应的模式的模型代码也写一下

    4.实现LRU算法

    实现一个LRU过期算法的KV cache, 所有KV过期间隔相同, 满足如下性质:

    1. 最多存储n对KV;

    2. 如果大于n个, 则随意剔除一个已经过期的KV;

    3. 如果没有过期的KV, 则按照LRU的规则剔除一个KV;

    4. 查询时如果已经过期, 则返回空;

    class?LRUCache?{
    ????constructor(capacity,intervalTime){
    ????????this.cache?=?new?Map();
    ????????this.capacity?=?capacity;
    ????????this.intervalTime?=?intervalTime;
    ????}
    ????get(key){
    ????????if(!this.cache.has(key)){
    ????????????return?null
    ????????}
    ????????const?tempValue?=?this.cache.get(key)
    ????????this.cache.delete(key);
    ????????if(Date.now()?-?tempValue.time?>?this.intervalTime){
    ????????????return?null
    ????????}
    ????????this.cache.set(key,?{value:?tempValue.value,?time:?Date.now()})
    ????????return?tempValue.value
    ????}
    ????put(key,?value){
    ????????if(this.cache.has(key)){
    ????????????this.cache.delete(key)
    ????????}
    ????????if(this.cache.size?>=?capacity){?//满了
    ????????????const?keys?=?this.cache.keys()
    ????????????this.cache.delete(keys.next().value)
    ????????}
    ????????this.cache.set(key,?{value,time:Date.now()})
    ????}
    }
    

    巧妙地利用了Map结构的key是有序的这个特点。普通Object的key是无序的。

    5.如何监控网页崩溃?

    基于 Service Worker 的崩溃统计方案

    随着 PWA 概念的流行,大家对 Service Worker 也逐渐熟悉起来。基于以下原因,我们可以使用 Service Worker 来实现网页崩溃的监控:

    1. Service Worker 有自己独立的工作线程,与网页区分开,网页崩溃了,Service Worker 一般情况下不会崩溃;

    2. Service Worker 生命周期一般要比网页还要长,可以用来监控网页的状态;

    3. 网页可以通过navigator.serviceWorker.controller.postMessage API 向掌管自己的 SW 发送消息。

    基于以上几点,我们可以实现一种基于心跳检测的监控方案:

    • p1:网页加载后,通过postMessageAPI 每5s给 sw 发送一个心跳,表示自己的在线,sw 将在线的网页登记下来,更新登记时间;

    • p2:网页在beforeunload时,通过postMessageAPI 告知自己已经正常关闭,sw 将登记的网页清除;

    • p3:如果网页在运行的过程中 crash 了,sw 中的running状态将不会被清除,更新时间停留在奔溃前的最后一次心跳;

    • sw:Service Worker 每10s查看一遍登记中的网页,发现登记时间已经超出了一定时间(比如 15s)即可判定该网页 crash 了。

    更多:https://zhuanlan.zhihu.com/p/40273861

    6.求代码输出,并说出为什么

    var?obj?=?{
    ????'2':3,
    ????'3':4,
    ????'length':2,
    ????'splice':Array.prototype.splice,
    ????'push':Array.prototype.push
    }
    obj.push(1)
    obj.push(2)
    obj.push(3)
    console.log(obj)
    

    答案:

    {
    ????'2':1
    ????'3':2,
    ????'4':3,
    ????'length':5,
    ????'splice':Array.prototype.splice,
    ????'push':Array.prototype.push
    }
    

    obj有长度,相当于类数组,调用数组的push,会在数组的最后加一项,第一次调用,相当于长度变为3,那么下标为2的那一项被赋值为1,下标是2,当其作为对象的key值的时候,会隐式调用toString方法转为字符串2,则和obj本来有的key '2'相同,原来的key为2的value就被覆盖了。以此类推后面的2个push。

    详情:https://github.com/LuckyWinty/fe-weekly-questions/issues/48

    7.node中的 setTimeout 和 setImmediate 有什么区别

    setImmediate() 和 setTimeout() 很类似,但是基于被调用的时机,他们也有不同表现。

    • setImmediate 设计在poll阶段完成时执行,即check阶段;

    • setTimeout 设计在poll阶段为空闲时,且设定时间到达后执行,但它在timer阶段执行

    执行计时器的顺序将根据调用它们的上下文而异。如果二者都从主模块内调用,则计时器将受进程性能的约束。举个例子,有如下代码:

    setTimeout(()?=>?console.log(1));
    setImmediate(()?=>?console.log(2));
    

    上面代码应该先输出1,再输出2,但是实际执行的时候,结果却是不确定,有时还会先输出2,再输出1。

    这是因为setTimeout的第二个参数默认为0。但是实际上,Node 做不到0毫秒,最少也需要1毫秒,根据官方文档,第二个参数的取值范围在1毫秒到2147483647毫秒之间。也就是说,setTimeout(f, 0)等同于setTimeout(f, 1)。

    实际执行的时候,进入事件循环以后,有可能到了1毫秒,也可能还没到1毫秒,取决于系统当时的状况。如果没到1毫秒,那么 timers 阶段就会跳过,进入 check 阶段,先执行setImmediate的回调函数。

    但是,如果是这样的情况,输出顺序就固定了,例:

    const?fs?=?require('fs');
    fs.readFile('test.js',?()?=>?{
    ?setTimeout(()?=>?console.log(1));
    ?setImmediate(()?=>?console.log(2));
    });
    

    在上述代码中,一定是先输出2,再输出1。因为两个代码写在 IO 回调中,IO 回调是在 poll 阶段执行,当回调执行完毕后队列为空,发现存在 setImmediate 回调,所以就直接跳转到 check 阶段去执行回调了,执行完成后再去到 timers 阶段,然后执行setTimeout。

    8.写一个正则,根据name取cookie中的值。

    function?get(name){
    ??var?reg?=?new?RegExp(name+'=([^;]*)?(;|$)');
    ??var?res?=?reg.exec(document.cookie);
    ??if(!res?||?!res[1])return?'';
    ????try{
    ??????if(/(%[0-9A-F]{2}){2,}/.test(res)){//utf8编码
    ??????return?decodeURIComponent(res);
    ????}else{//unicode编码
    ??????return?unescape(res);
    ????}
    ??}catch(e){
    ????return?unescape(res);
    ??}
    }
    

    正则表达式中重点看这几句代码: '([^;])', 意思是匹配str=后面的不为; ([^;]表示非集, 也就是所有不为;的字符都能被匹配)的字符串, 该字符串出现0或更多次(), 之后将匹配到的字符串放入第一个捕获组.

    详情:https://github.com/LuckyWinty/fe-weekly-questions/issues/32

    9.在不改变html结构的情况下,写出至少7种方法实现以下布局。

    要求:左边2列,右边1列,中间自适应

    ????<div?class="parent"?style="width:?200px">
    ????????<div?class="child?child1"?style="width:?20px"></div>
    ????????<div?class="child?child2"?style="width:?20px">2</div>
    ????????<div?class="child?child3"?style="width:?20px">3</div>
    ????</div>
    

    答案:

    /*?1?*/
    ????.parent{
    ????????background-color:?burlywood;
    ????????display:?flex;
    ????}
    ????.child{
    ????????background-color:?black;
    ????????font-size:?20px;
    ????????color:?white;
    ????}
    ????.child3{
    ????????margin-left:?auto;
    ????}
    
    /*?2?*/
    ????.parent{
    ????????background-color:?burlywood;
    ????????position:?relative;
    ????}
    ????.child{
    ????????font-size:?20px;
    ????????color:?white;
    ????}
    ????.child1{
    ????????background-color:?black;
    ????????position:?absolute;
    ????????left:?0;
    ????}
    ????.child2{
    ????????background-color:?black;
    ????????position:?absolute;
    ????????left:?20px;
    ????}
    ????.child3{
    ????????background-color:?black;
    ????????position:?absolute;
    ????????right:?0;
    ????}
    
    /*?3?*/
    ????.parent{
    ????????background-color:?burlywood;
    ????}
    ????.child1{
    ????????background-color:?black;
    ????????float:?left;
    ????}
    ????.child2{
    ????????background-color:?red;
    ????????float:?left;
    ????}
    ????.child3{
    ????????float:?right;
    ????????background-color:?blue
    ????}
    
    /*?4?*/
    ????.parent{
    ????????background-color:?burlywood;
    ????????display:?table;
    ????}
    ????.child{
    ????????background-color:?black;
    ????????display:?table-cell;
    ????????height:?20px;
    ????}
    ????.child3{
    ????????display:?block;
    ????????margin-left:?auto;
    ????}
    
    /*?5?*/
    ????.parent{
    ????????background-color:?burlywood;
    ????????position:?relative;
    ????}
    ????.child{
    ????????background-color:?black;
    ????????position:?absolute;
    ????????top:0;
    ????????left:0;
    ????}
    ????.child2{
    ????????transform:?translate(20px,?0);
    ????}
    ????.child3{
    ????????transform:?translate(180px,?0);
    ????}
    
    /*?6?*/
    ??.parent{
    ????????background-color:?burlywood;
    ????????display:?grid;
    ????????grid-template-columns:?repeat(10,?1fr);
    ????}
    ????.child{
    ????????background-color:?black;
    ????????font-size:?20px;
    ????????color:white;
    ????}
    ????.child3{
    ????????grid-column:?10?/?11;
    ????}
    
    /*?7?*/
    ????.parent{
    ????????background-color:?burlywood;
    ????????font-size:?0;
    ????}
    ????.child{
    ????????background-color:?black;
    ????????display:?inline-block;
    ????????font-size:?20px;
    ????????color:?white;
    ????}
    ????.child3{
    ????????margin-left:?140px;
    ????}
    

    10.用css画一个扇形?

    width:?0;
    height:?0;
    border:?solid?100px?red;
    border-color:?red?transparent?transparent?transparent;
    border-radius:?100px;
    

    说明

    本文部分题目及答案来源于网络,如有错误,欢迎纠正,如有侵权问题,麻烦微信联系 winty230 交涉处理。

    最后

    • 欢迎加我微信(winty230),拉你进技术群,长期交流学习...

    • 欢迎关注「前端Q」,认真学前端,做个专业的技术人...

    原创不易,点个在看支持我吧