前端进阶、面试必会知识

9,339 阅读11分钟

写在前面

为什么要写这篇文章

技术研发人员被称为“幕后工作者”,工作特点是安静的研发多于交流表达,而面试是一个以表达窥探研发能力的过程,因此,能不能把问题理解透彻、能不能表达清楚、能不能进行举一反三,决定了能不能将能力完美的展现出来,同时也决定了最终的面试结果。本文旨在提升在面对问题时的:分析问题的能力、表达能力 以及 相关知识拓展能力。

内容说明

本文不搬运陈年面试题,将从全新角度总结面试题,从审题开始,教你总结、归纳、递进、扩展,形成自己的知识体系;另外,本文会持续更新,适合收藏,再次打开时,本文内容已从春种幼苗长成参天大树。

看完能学到什么

构建前端知识网,形成自己的前端知识体系,能够举一反三,融会贯通

文章结构

本文将按知识分类整理,可在PC端右侧书签栏针对性分类阅读,内容将持续更新。同时,文无第一,武无第二,如有错误及纰漏,望能斧正。

HTML篇

1. 说说你知道哪些页面布局方式?他们各有什么优缺点?

从早期前端发展到现在,经历了一下发展历程:table布局,position布局,浮动布局,栅格布局,flex弹性盒子布局

table布局:
  优点:不需要使用任何CSS配合就可搭建正题布局;兼容性强,所有浏览器都支持该元素;
  缺点:任意单元格的布局属性改变将引起整个表格的回流,耗费性能;各个浏览器对table基础属性实现不同,样式有差异;难以适应复杂业务需求;

position布局:
  优点:利用position的五个属性(static、relative、absolute、fixed、sticky)改变元素在文档流中的位置,使用灵活;
  缺点:当为元素设置定位时,往往还涉及到为父元素设置定位,额外增加了复杂度;元素脱离文档流后可能引起父元素高度塌陷,需要对父级元素做处理;对于sticky在部分版本浏览器不支持,截止发文,在支付宝小程序也不支持sticky属性。

浮动布局:
  优点:可以自由改变元素在同级元素之间的排列顺序;
  缺点:需要做清除浮动等后续工作,否则会造成父级元素高度塌陷、影响其他元素布局等问题;。
样式有差异;难以适应复杂业务需求;

栅格布局:
  优点:个人认为它是table布局的改良版,它跟table布局一样,都引入二维空间行列的概念。栅格布局使用百分比为单位,没有基础样式,避免了table的缺点;
  缺点:原生的栅格布局浏览器对其支持性并不好,反而是集成了栅格布局的bootStrap框架兼容性做的更好,因此大多用的都是bootStrap作为布局工具。

flex布局:
  优点:移动端布局神器,在不使用任何UI框架的情况下可以快速形成布局;一整套的属性可以达到解决大多数布局问题;
  缺点:属于CSS3引入的属性,仅适用于IE9以上,低版本需要兼容处理;同时,需要掌握繁琐的属性设置;flex属性占用了css的display属性,在部分场景下需要设置特定display属性时,只能另寻它法。

JS篇

1. 说说什么是原型链

原型是函数特有的属性,称为:prototype。prototype属性是一个对象,这个对象的作用是:存储需要共享的属性和方法,以便在自己作为构造函数时传给函数实例。prototype对象中有一个自带属性constructor,它是一个函数指针,指向的是实例对象的构造函数。函数还有一个属性:constructor,它是一个指针,指向的是函数构造函数。函数实例依然可以作为构造函数,生成新的函数实例,构造函数与函数实例之间原型形成的关系,称为原型链。原型链的作用是实现方法和属性复用,减少重复代码,节省存储空间,也就是所说的实现继承。原型继承的缺点是,如果共享的属性是引用类型,则会造成所有实例均可更改构造函数属性,另一个弊端是,在生成函数实例时,没办法向构造函数传递参数,做不到自定义属性值。因此,鉴于这两个缺点,常常原型和构造函数一起使用,形成组合继承,组合继承也是JS中继承最常用的模式。

2 说说闭包

闭包本质上是一个函数,这个函数特点是:能够访问另一个函数作用域内的变量。
闭包的作用有:1)避免变量污染全局;
       2)模拟块级作用域,封装私有方法,暴露公共方法属性;
       3)模拟缓存,局部存储数据;
闭包危害: 主要是垃圾回收问题和内存泄漏问题。
       1)闭包函数在执行后无法被销毁,始终存在环境中;
       2)闭包中使用到的变量无法被垃圾回收,造成内存泄漏。

3 什么是内存泄漏?你知道哪些?

内存泄漏指的是:因缺陷或错误造成的不再被使用的内存无法被回收,从而造成内存浪费的情况。
常见的有:
    1) 意外的全局变量;
    2) console.*打印方法;
    3) 闭包;
    4) DOM泄漏;
    5) 未清理的定时器;

4 前端实现动画的方式有哪些?为什么建议使用 requestAnimationFrame

HTML提供了:canvas、SVG
CSS提供了:transition、animation
JS提供了:requestAnimationFrame()方法 和 setTimeout
requestAnimationFrame 是HTML5提出的API,它具有以下优点:
    CPU节能:setTimeout使用异步任务队列的方式实现动画,它的缺点是卡顿丢帧严重,其次一个很大的问题是,即使当前页面被最小化,或被挂起,动画依然会执行,而这个时候由于用户是看不到的,完全没有意义,极大的浪费了CPU性能;requestAnimationFrame是被系统调用的,也就是说,它的刷新图像间隔能够跟屏幕刷新界面光点频率保持一致,当页面被最小化或被挂起时,页面动画也会暂停,再次处于active状态时,会从上次暂停的位置继续执行,节省了CPU开销。
    自动节流:requestAnimationFrame能够保证在刷新间隔内只会执行一次刷新函数,既不会重复执行导致好性能,又能保证不丢帧,保持流畅性。
    缺点:
     requestAnimationFrame是HTML5提供的API,在部分浏览器上兼容存在问题,需要加前缀或不支持,因此需要对该方法进行ployfill,实现在不兼容的情况下优雅降级使用,直到最后使用setTimeout实现动画为止。

5 说说深拷贝与浅拷贝原理及实现方法

深浅拷贝针对的是引用类型,在JS中,引用类型存放在堆内存中,访问时,通过栈内存中的指针进行访问,基础类型不存在深浅拷贝问题。
浅拷贝:在栈内存中生成一个新指针,指向内存中的引用数据;
浅拷贝实现
     1) 赋值;
     2) 针对数组:var newArr = arr.concat();
     3) 针对数组:var newArr = arr.slice();
     4) var newObj = Objcet.create(obj);
     5) var newObj = Objcet.assign({},obj);
深拷贝: 在堆中申请独立空间存储一份新数据,并在栈内存中生成一个新指针指向堆内数据。
深拷贝实现
     1) var newObj = JSON.parse(JSON.stringify(obj));当属性值为undefined或函数时,会忽略,因此要慎用。
     2) 递归拷贝,可以封装成一个工具函数,全局使用;

练习题

6 说说防抖与节流

防抖和节流针对的是用户频繁触发或调用某个函数造成客户页面端卡顿或过多耗费性能和服务器资源的问题。两个方法本质上都是对频繁触发做延迟处理,只是处理的方式不同,我在这里详细写了防抖与节流,并给出了封装函数,请移步这里:
juejin.cn/post/684490…

7 请用ES5实现const

分析:const与其他定义变量的方式不同点在于,const定义的基本类型,其值不可更改,const定义的引用类型,指向堆内存的地址不能更改(注意:此处说的是内存地址不变,而不是内存地址指向的内存空间里所存储的数据不变)

思路:要想实现变量的值不被重写,如果我们能监听到变量赋值操作,我们就可以阻止变量赋值,进而就可以实现赋值拦截。问题转化成监听赋值操作,首先想到的便是Object.defineProperty()方法,它可以定义对象属性的基础属性,包括取值赋值。但是这里有一个问题:这个方法是针对对象的,那全局变量怎么办?这里要注意的是:全局变量实际上是全局对象window的属性

有了这个知识,就可以动手写逻辑了: 要注意的一点:ES5中没有块级作用域的概念,而const是可以作用于域块级作用域的,所以,即使我们模仿实现了const功能,但是没有模仿实现块级作用域的效果,与const还是有差异的。

8 说说原型、隐式原型、实例、构造函数之间的关系

我相信,读到这里的读者一定了解过这几个概念,只是有种时而清楚时而模糊的感觉,有一种:我理解,但是我没办法解释给你听的感觉。

如果你也有这种感觉,恭喜你,来对地方了。今天,我就把绝世秘籍传输给你,先点个关注和赞,免得待会儿突然醍醐灌顶就忘了。

点完了吗?要开始了哦~

1. 首先说说,为什么我们看了那么多关于原型的文章,还是解释不清呢?原因有三:

a)因为每次看你都是很认真的记住了单个或者零散的几个之间的关系和区别,这几个大家族之间的关系到底是怎么关联起来的,不清楚。
b)某一次理解了好久,终于清楚了,后来,又模糊了,为啥呢?因为记忆不深刻
c)每次都是文字理解,文字记忆,再次复习起来要复习的太多,不好复习,久而久之就忘了。
今天,终极大法来了~先说方法:把以下图看5遍,想5遍,自己画3遍,每天回忆两遍,不出一个星期,完全记忆清楚了。上图:


关系图说明:

. 构造函数通过prototype属性指向构造函数的原型Person.prototype

. 构造函数的原型(Person.prototype)通过constructor属性指回构造函数Person

. 构造函数Person通过new 关键字生成实例person

. 实例person通过__proto__(读作:double underline proto 或 dunder proto)指向构造函数的原型对象。

在这里要注意:ECMA标准指出要提供一个属性,使得原型能够通过该属性访问到构造函数的原型对象。

注意:要理解记忆,多次复习,才能做到融会贯通。

未完,待更新…… 记得点个关注和赞哦~

文末

只写看得懂、读得懂、有价值的技术文章;看完觉得有收获,点赞 + 关注,平台会为你推荐更多优质主题文章;

在准备面试?来交流一下吧,每天一到面试题提升自我;准备进阶高级全栈?来聊聊进阶之道,少走弯路;敲代码累了?来群里聊聊天吧,让工作更高效。

由于限制,目前已满200,只能通过邀请加入,所以, 所以,请搜索公众号【前端进阶面试内推】,我邀请进群。来这里,找到更多志同道合的前端伙伴~