前端面试复盘专题(一):复习大纲及蜕变计划

14,662 阅读16分钟

前言

距离上次更新已经过去了好久,在这几个月里,虽然没有更新文章,但是自己也没有闲着,出去转了转各大公司的前端招聘要求,真正的体验了一把前端的行情和走势。在经历了这些之后,我开始重新修正自己的学习方向,完善自己的知识架构体系和学习方法,我会将我知道的和经历的倾囊相授,之所以写这些,不是要标榜自己有多厉害,只是想把自己踩过的坑走过的弯路分享出来,帮助真正热爱前端的同学站在我们前人的肩膀上跨越技术障碍,留足精力去探索前端更有趣、自己真正喜欢的东西,同时也是对自己在这几个月的一个交代;在文章的末尾,我会发起一个“前端蜕变计划”,具体的信息我会在文章最后说明,欢迎热爱前端的小伙伴一起加入。

专题介绍

首先,专题是复盘系列,我会根据自己目前亲身接触的比较中肯的形式来定整体体系,对于比较极端和小众的形式,我也会顺手提到,防止意外踩坑。整个专题系列耗时会比较长,文章也会比较多,我会根据先概括再细节的方式逐级展开。

根据面试轮次,按照技术层次分,顺利的话,会分为5轮,这5轮分别是层级递进的,各轮考察内容主要如下:

graph TD
第一轮:前端基础知识掌握情况及实际编程能力
graph TD
第二轮:项目开发能力及发现和解决实际问题能力
graph TD
第三轮:技术架构原理和JavaScript设计模式以及数据结构算法
graph TD
第四轮:自我职业规划和对行业新技术了解以及未来发展的的认知
graph TD
第五轮:你期望的工作方式和你是如何确定自己期望薪资标准的

以上的面试层次是中大型公司的流程,大家可以参照5轮面试的主体结构来构建自己的知识体系,针对性的复习,另外因为涉及到的知识非常的广泛,更新时间会非常的长,如果等不及,可以私聊我进行讨论。在每个专题我会只列出几道题,但是在给出解答思路的时候会进行外延拓展,还是那句话,答案不重要,涵盖的知识如何串起来,让面试官真正认识到你是真的懂,这才是关键。

本文专题

面试轮次:第一轮

考察能力:前端基础知识掌握情况及实际编程能力

主体知识:JS基础----堆栈内存闭包作用域

题目:

1parseInt()和Number()有什么区别?

2var 和 const的区别?

3、如何实现一个函数add使得:add(1)(4,5,6)(7,8)(10) 输出 414、说说ES6里面对数字类型的增强特性有哪些?

题目解答思路

题目一 parseInt()和Number()有什么区别?

考查知识: JS数据类型、为什么会有隐式转换

主体思路:先答这两个API的作用是什么,再说具体哪不同(入参,过程,结果),再说为什么会出现这种原因;

示例答案:parseInt和Number都是两个用于将入参转为数字的方法。parseInt是将入参转化为指定进制的整数,而Number是将传入的参数转换成数字类型的值,两者在允许接收的参数个数上不同,同时在转换结果上也可能不同,这是第一点区别;第二点区别在于转换过程中,parseInt会尽可能的将传入的参数转为数字,直到遇到不能转换为数字的字符,而Number会在转换前对入参进行扫描,只要含有不能转换成数字的字符,全部返回NaN;第三点在于,对于特殊类型的处理,对于null和undefined,parseInt均会返回NaN, 而Number返回0和NaN;

题目二 var 和 const 有什么区别?

考查知识: JS定义变量的方法,以及为什么要新增定义变量的方式

主体思路:先答这两个API的作用是什么,再说具体哪不同,再说为什么会出现这种原因;

示例答案:var和const都是声明变量的方式,而他们之间的区别,主要在以下几个方面:

  1)兼容性和语法支持;varJS最早声明变量的方式,只要支持JS,都支持var声明变量的方式,而constES6新加入的语法,在部分不支持的环境中需要使用工具转换成var的写法;
  
  2)变量提升的区别;var声明的变量会存在着变量提升的特性,也就意味着在变量正式被赋值之前都可以被读取,而const声明的变量不具备变量提升的作用;
  
  3)与全局对象的关系;在全局环境中,使用var申明的变量,既是一个全局的变量同时还是全局对象window的一个属性,而使用const声明的变量仅仅是一个变量;
  
  4)重复声明;使用var声明的变量,允许在相同的环境中再次声明一个同名变量,而使用const声明的变量,不允许再次声明同名变量;
  
  5)暂时性死区;const具有暂时性死区的特性,在变量被声明赋值之前,访问变量会出现报错的问题,这是ES6为严格语法规则加入的特性,保证了变量在声明之后才可读取;
  
  6)与块级作用域的关系;constlet的出现很大的一个原因是因为在ES6中除了以前的全局作用域和函数作用域,新增了块级作用域的概念,而const的有效范围其实就是块级作用域,再一次细分了作用域的维度大小;
  
  7)为什么会出现const呢?
  ES规范的出现是为了改变JS本身存在的问题,使其能够安全稳定的在较大的综合项目中稳定运行,因此对于一些影响因素重新添加新的语法规则得以改善,同时又保持原有语法正常支持;

题目三: 如何实现一个函数连续相加函数add,使得:add(1)(4,5,6)(7,8)(10) 输出 41 ?

主体思路:根据题目信息,每一次add执行完成后还可以再次执行,意味着add执行完成后返回的是一个函数,而这个函数可以将所有传入的参数进行累加,所以,问题就变成了:

1)如何记录下每一次传入的参数;

2)如何在执行后依然返回一个函数,并且还能实现累加;

3)如果返回的是一个函数,如何能实现在访问执行结果的时候返回一个数字?

要解决参数记录,最容易想到的就是设置一个全局变量,将每次传入的参数都记下来,然后再求和;这是最容易想到的一个方法,但是这个方法有个弊端,那就是在同一个命名空间,分别执行两次相同参数的函数,得到的结果完全不一致,而且,后一次执行的结果是前一次结果的两倍,原因就在于虽然实现了记下每一次的参数,但是理想的状况是:当我重新执行的时候,我希望的结果是初始值,而不是被上次执行结果污染的;写成代码就是:

add(1)(4,5,6) // 16 add(1)(4,5,6) // 32

而我需要的是: add(1)(4,5,6) // 16

add(1)(4,5,6) // 16

所以,使用全局变量去解决参数记录问题是存在问题,那么就得另外想办法;那能解决这个问题的另一个办法就是闭包,闭包能够实现我们在外部访问函数内部的变量,理论上保存变量的问题是解决了;那么第二个问题是执行结果是一个函数,在闭包里这也不是问题,因为闭包在大多数情况下最明显的特征就是返回一个被外部占用的变量,这点也满足要求。

所以根据上述思路,伪代码可以写成这样:


function add(arg){
    
    arg = oldArg + arg;  // 参数合并,并且首次执行参数是初始值

    return function(arg){  // 返回一个函数,将合并后参数继续传入
     // ……
     
    }
}

现在还存在最后一个问题,如何在访问的时候能够返回一个数字?根据前面的思路,函数执行后会返回一个函数,而函数是个引用类型的值,对于引用类型的值,当访问值时,实际上访问的是引用类型中[Symbol.toPrimittive]、valueOf、toString去获取引用类型的原始值,所以我们只需要选取其中一个重写其方法就可以了。现在问题基本都理清了,按照思路,直接写出答案:

function add(...arg){

  function proxy(...innerArg){

    arg = [...arg,...innerArg];

    return proxy
  }

  proxy.toString = function(){

    return arg.reduce(function(total, item){return total + item}, 0)
  }

  return proxy
}

需要注意的是,这里的proxy并不是那个Proxy函数,如果觉得绕的话,可以换成其他名字都行。

题目四: 说说ES6里面对数字类型的增强特性有哪些?

主体思路:

限定很明确,是对数字类型,因此尽可能的详尽一点概括总结新特性,既考察你对ES6的了解程度,又考察总结临时概括能力。

参考答案:

ES6对数字类型能力支持主要出于两方面的考虑,一个是改善既有的缺陷,再有就是提供能力增强;

先说缺陷弥补:

   1)增加Object.is()方法弥补等价判断缺陷;
       在以往 +0 === -0 结果是true, 但是有时候我们希望的是只要是完全一样,结果就返回true,
       但凡有差异,结果就返回false, 但事实并非如,江湖上一直流传着以下代码:
  +0 === -0  // true
           
  NaN === NaN  // false

这种情况让人很是头疼,在特定业务下,不得不自己写工具函数去判断是否真的一致,ES6为了弥补这一问题,新增了Object.is(a,b)方法,目的就是要解决这种判断不一致问题,再来看看弥补之后的结果:

Object.is(+0, -0) // false

Object.is(NaN,NaN)  // true

这才是符合我们认知的等价。

2)增加Number.EPSILON,可以用来判断两数相等

JS对数字的表示不区分整型和浮点型,通通都用双精度64位浮点型表示,这就导致在转换一些数字时,没办法完全准确的用二进制表示,所以才会出现经典的0.1 + 0.2 !== 0.3 问题,在设计交易金额时,处理精度非常的老火,要么自己写处理函数做先放大后缩小,要么采用第三方工具,总之就是战战兢兢;ES6新增Number.EPSILON,他的值时2的-52次方,我们可以借用该值极小的特性,认为只要两个数之间的差值小于该值,就可以认为两数相等,虽然依然无法一步到位省去比较过程,但是可以简化我们的比较逻辑,封装之后挂载全局还是很好用的

再说能力增强:

1)bigInt bigInt要解决的问题是超出最大安全数和小于最小安全数之后,数据会失真的问题,虽然我们可以使用字符串的形式表示,却无法依靠字符串做数字运算,还得实时防着后端给的数字会超出范围,在计算的时候也需要借助后端能力,bigInt能够实现数据不失真表示,还能进行运算,可谓是一大福音;

2)最大安全数和最小安全数 准确的说叫最大安全整数和最小安全整数,表示为:Number.MAX_SAFE_INTEGER 和Number.MIN_SAFE_INTEGER,对应数值分别为2^53 和 2^(-53),超出该范围的值会失真,实际项目中,可以借此做安全性判断,结合bigInt综合应用;

前端蜕变计划

什么是前端蜕变计划?

前端蜕变计划是一项面向热爱并致力于努力提升自我的前端开发者的公开的学习提升计划。

计划要解决什么问题?

前端蜕变计划要解决的问题主要是:有想法但是没毅力坚持、有毅力但是方法收效甚微和有想法但是不知道从哪入手的前端学习者的困惑。

参与后我能得到什么?

思维习惯:

持续学习习惯: 有没有思考过一个问题:为什么到现在,即使是初入前端,依然能拿到很高的工资?原因就在于,虽然前端是一个需要积累的职业,但是迭代速度非常的快,十年前你需要懂IE兼容的办法,但是现在呢,你只要学了原生JS和vue/react,你就能拿到满意的offer,快速发展带来的不仅仅是学习成本的增加,同时也意味着再任何时候,只要你掌握了当前比较热门的技术,你就能从前端分到一杯羹,然后在工作中再去弥补自己的基础知识,这对于新人非常友好,但是对于老前端,却需要持续的学习,才能在技术上想必新手有比较大的职业优势,毕竟新手对于薪资和加班要求都没那么高。

自我驱动: 人都是有惰性的,很少有人能坚持长时间的去做一件事,除了学习,外界的一切都具有吸引力,所以这个计划要达到的目标其中一个就是要实现自我意识觉醒,找到舒服的学习方式,从而实现自己主动去学习,前期我们会定期推送题目,提醒学习,渐渐的养成习惯,实现自我主动学习,遇到难题了再回过头来交流。

记答案!==会了: 前端知识有很多知识是没有权威讲解为什么是这样的参考资料的,对于一些反人类的知识点,即使想问为什么,也不要知道找谁问,慢慢的,对于一些题记住了答案,却不知道原理,所以,计划要解决的问题就是让你想问为什么的时候,有人会,并且还能给出详细的分析,理解后再记忆,这样的记忆才有意义。

持续总结: 前端知识杂而多,并且要想掌握深刻,不是那么容易的,另外,在不同的阶段,你对同一个知识点的理解角度和深度也会不一样,你需要记住那些面试爱问而实际工作中又碰不到的知识点,同时也能

学习方法:

项目驱动自我能力: 一直把做项目当做是自我学习之外的事情,直到有一天遇到了一个只从实际项目中获取知识的高手,我才意识到自己的想法存在误区,我要说的是,想办法从实际工作项目中汲取营养,如果觉得汲取不到,那一定是方法出现了问题,想办法去请教熟悉这种学习方法的人,从他们那取经,同时,工作之外的自我扩展也不能放下,毕竟工作中用到的知识不等于实际面试中考察的知识,所以,尽可能的两者兼顾。

构建知识树: 我遇到的比较厉害的高手,都是有自己的知识架构树,一定不要嫌弃构建知识树耗时还耗力,他能具象化你的知识体系,让你真正的从纸面上看到自己会哪些,哪些知识还是空白的,同时也让你再次从零复习时快速建立知识体系。

专题兴趣组: 找到志同道合的人,针对某个专题,听听他们怎么理解,不要总是闷在自己的世界里,思想的碰撞才会激发出更多的学习乐趣;小组的人不需要太多,3-8人足矣,要保持足够的好学态度,互相鼓励,共同探讨。

刷题: 这个技巧相信大多数同学都用过,以战养战,如果刷题方法得当,能够实现短期内在编程能力实战上有比较大的提升,但是一定要得当,如何才能去评估方法是否得当呢?有个比较简单的办法,做一道题目,一个星期后你还会写,并且保证下次碰到相同类型的题目能够有思路,那么你就真的掌握了刷题技巧,反之,你该思考到底是哪个环节出现了问题,不要毫无目的的乱刷题,背题目是不管用的,背了忘,忘了背,既没有效果,还为难了自己。

心态:

放下焦虑: 前端发展太迅速了,以至于大家把握不准前端在此时此刻的行情,于是乎总有一部分抱有目的的人说前端饱和了,前端凉了等相关谣言,如果你对前端后一定的了解,这些话自然不攻自破,坏就坏在这些人对于这个论点给出明确的论据,让你即使不相信,但内心依然产生波动,不自主的陷入到职业焦虑中;另外还有一种焦虑是技术焦虑,所谓的技术焦虑就是,技术更新迭代太快,担心自己跟不上发展潮流而被淘汰,但实际上,没有人能够实现驾驭所有新老技术,也没必要一味的求新,而对当前已掌握的技术浅尝辄止,否则就会造成样样都知道,样样都不熟的状态,如果你不知道该如何调整,欢迎加入加入中,一起克服焦虑。

学会焦虑: 有的同学会问,刚刚你不才说了要放心焦虑吗?这咋还说要学会焦虑呢,这里我要说的是,对于别人扔给你的无辜焦虑,你应该要学会丢掉,但是自己要有危机意识,因为,你不学习,长期以往,就真的会出现工资倒挂的情况,你应该要产生内驱,但是这个度,你要把握好,否则要么着魔,要么抑郁。

我如何参与?

我会根据你对技术的热爱程度,分为狂热和热爱,对于狂热,我会拆分出小组,一组7-10人,对于热爱,我会统一合并到一起,人数可能较多,所以大家可能通过微信搜索公众号【前端进阶指南】来参与到计划中,希望一年后再次想起今天的决定,发自内心的觉得今天选对了,不拼一把,你怎么知道自己是人才还是废柴。

最后

最后送给大家一段我很喜欢的话:

"The best time to plant a tree was 10 years ago. The second best time is now."

种一棵树最好的时机是十年前,其次是现在。

我是格局,带你看有深度的前端世界,搭建适合自己的知识架构,关注我,跑的更快一点。