settimeout需要清除吗_前端20个真正灵魂拷问,前端初级到中级你还需要这个!

前言

先赞再看,养成习惯~

网上参差不弃的面试题,本文由浅入深,让你在做面试官的时候,能够辨别出面试者是不是真的有点东西,也能让你去面试中级前端工程师更有底气。但是切记把背诵面试题当成了你的唯一求职方向

下篇将是非常硬核的源码,原理,自己编写框架和库等,如果感觉写得不错,可以关注给个star~

推荐一个视频:

点击观看--->2020年这9个项目助你成为前端大神!

越是开放性的题目,更能体现回答者的水平,一场好的面试,不仅能发现面试者的不足,也能找到他的闪光点,还能提升面试官自身的技术

1.Css和Html合并在第一个题目,请简述你让一个元素在窗口中消失以及垂直水平居中的方法,还有Flex布局的理解

标准答案:百度上当然很多,这里不做阐述,好的回答思路是:

  • 元素消失的方案先列出来, display:none和visibility: hidden;的区别,拓展到vue框架的v-if和v-show的区别,可以搭配回流和重绘来讲解

回流必将引起重绘,重绘不一定会引起回流

回流(Reflow):

当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流
  • 下面内容会导致回流:
  • 页面首次渲染
  • 浏览器窗口大小发生改变
  • 元素尺寸或位置发生改变
  • 元素内容变化(文字数量或图片大小等等)
  • 元素字体大小变化
  • 添加或者删除可见的DOM元素
  • 激活CSS伪类(例如::hover)
  • 查询某些属性或调用某些方法
  • 一些常用且会导致回流的属性和方法:
  • clientWidth、clientHeight、clientTop、clientLeft
  • offsetWidth、offsetHeight、offsetTop、offsetLeft
  • scrollWidth、scrollHeight、scrollTop、scrollLeft
  • scrollIntoView()、scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()
程序猿的生活:前端只需要掌握这些,你也能拿8K!((附简历模板102份)最完整面试题含答案)​zhuanlan.zhihu.com

重绘

当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。

性能影响对比:

493436d3b62ec5ec323346f07bde73c4.png

原文出处,感谢作者

  • 列出元素垂直居中的方案,以及各种方案的缺陷

16种居中方案,感谢作者

  • 讲出flex常用的场景,以及flex 1做了什么

阮一峰老师的Flex布局

上面的问题如果答得非常好,在重绘和回流这块要下大功夫。这点是前端性能优化的基础,而性能优化是前端最重要的核心基础技能点,也是面试官最看中的基础之一

2.你对This了解吗,有自己实现过call,apply,bind吗?

50行javaScript代码实现call,apply,bind

这是一个很基础的技能点,考察你对闭包,函数调用的理解程度,我感觉我写得比较简单容易懂

3.如何减少重绘和回流的次数:

9ae2b07c92351a0df066470dce918796.png

4.你对前端的异步编程有哪些了解呢

这个题目如果回答非常完美,那么可以判断这个人已经脱离了初级前端工程师,前端的核心就是异步编程,这个题目也是体现前端工程师基础是否扎实的最重要依据。

还是老规矩,从易到难吧

传统的定时器,异步编程:

setTimeout(),setInterval()等。

缺点:当同步的代码比较多的时候,不确定异步定时器的任务时候能在指定的时间执行。

例如:

在第100行执行代码 setTimeout(()=>{console.log(1)},1000)//1s后执行里面函数

但是后面可能有10000行代码+很多计算的任务,例如循环遍历,那么1s后就无法输出console.log(1)

可能要到2s甚至更久

setInterval跟上面同理 当同步代码比较多时,不确保每次能在一样的间隔执行代码,

如果是动画,那么可能会掉帧

ES6的异步编程:

promise generator async
程序猿的生活:打造全网web前端全栈资料库(总目录)看完学的更快,掌握的更加牢固,你值得拥有(持续更新)​zhuanlan.zhihu.com
new promise((resolve,reject)=>{ resolve() }).then()....
 缺点: 仍然没有摆脱回掉函数,虽然改善了回掉地狱
 
 generator函数 调用next()执行到下一个yeild的代码内容,如果传入参数则作为上一个

`yield`的
返回值
 缺点:不够自动化

 async await 
 只有async函数内部可以用await,将异步代码变成同步书写,但是由于async函数本身返回一个
promise,也很容易产生async嵌套地狱

requestAnimationFrame和requestIdleCallback:

传统的javascript 动画是通过定时器 setTimeout 或者 setInterval 实现的。但是定时器动画一直存在两个问题

第一个就是动画的循时间环间隔不好确定,设置长了动画显得不够平滑流畅,设置短了浏览器的重绘频率会达到瓶颈,推荐的最佳循环间隔是17ms(大多数电脑的显示器刷新频率是60Hz,1000ms/60);

第二个问题是定时器第二个时间参数只是指定了多久后将动画任务添加到浏览器的UI线程队列中,如果UI线程处于忙碌状态,那么动画不会立刻执行。为了解决这些问题,H5 中加入了 requestAnimationFrame以及requestIdleCallback

requestAnimationFrame 会把每一帧中的所有 DOM 操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率

在隐藏或不可见的元素中,requestAnimationFrame 将不会进行重绘或回流,这当然就意味着更少的 CPU、GPU 和内存使用量

requestAnimationFrame 是由浏览器专门为动画提供的 API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了 CPU 开销

性能对比:

906d22fe6e935bd200f9358d575615a4.png

requestAnimationFrame的回调会在每一帧确定执行,属于高优先级任务,而requestIdleCallback的回调则不一定,属于低优先级任务。

我们所看到的网页,都是浏览器一帧一帧绘制出来的,通常认为FPS为60的时候是比较流畅的,而FPS为个位数的时候就属于用户可以感知到的卡顿了,那么在一帧里面浏览器都要做哪些事情呢,如下所示:

a55af3217a4a0eeff197e535d2afa3f8.png

图中一帧包含了用户的交互、js的执行、以及requestAnimationFrame的调用,布局计算以及页面的重绘等工作。

假如某一帧里面要执行的任务不多,在不到16ms(1000/60)的时间内就完成了上述任务的话,那么这一帧就会有一定的空闲时间,这段时间就恰好可以用来执行requestIdleCallback的回调,如下图所示:

81e27f54a765ebeea757cde95eb47a8a.png

5.简述浏览器的Eventloop和Node.js的Eventloop

浏览器的EventLoop

14b5c76f9c728ca36a1238ac56dcae6d.png
不想解释太多,看图

Node.js的EventLoop

28b33b65008a636545b4fb04551b9c7b.png

特别提示:网上大部分Node.js的EventLoop的面试题,都会有BUG,代码量和计算量太少,很可能还没有执行到微任务的代码,定时器就到时间被执行了

6.闭包与V8垃圾回收机制:

JS 的垃圾回收机制的基本原理是:

找出那些不再继续使用的变量,然后释放其占用的内存,垃圾收集器会按照固定的时间间隔周期性地执行这一操作。

V8 的垃圾回收策略主要基于分代式垃圾回收机制,在 V8 中,将内存分为新生代和老生代,新生代的对象为存活时间较短的对象,老生代的对象为存活事件较长或常驻内存的对象。

87e53b021b6ac8bbe6a3545b6cc2310e.png

V8 堆的整体大小等于新生代所用内存空间加上老生代的内存空间,而只能在启动时指定,意味着运行时无法自动扩充,如果超过了极限值,就会引起进程出错。

Scavenge 算法

在分代的基础上,新生代的对象主要通过 Scavenge 算法进行垃圾回收,在 Scavenge 具体实现中,主要采用了一种复制的方式的方法—— Cheney 算法。

Cheney 算法将堆内存一分为二,一个处于使用状态的空间叫 From 空间,一个处于闲置状态的空间称为 To 空间。分配对象时,先是在 From 空间中进行分配。

当开始进行垃圾回收时,会检查 From 空间中的存活对象,将其复制到 To 空间中,而非存活对象占用的空间将会被释放。完成复制后,From 空间和 To 空间的角色发生对换。

f437b865d3b95cb9aca5ee7d566a4742.png

当一个对象经过多次复制后依然存活,他将会被认为是生命周期较长的对象,随后会被移动到老生代中,采用新的算法进行管理。

还有一种情况是,如果复制一个对象到 To 空间时,To 空间占用超过了 25%,则这个对象会被直接晋升到老生代空间中。

标记-清除和标记-整理算法

对于老生代中的对象,主要采用标记-清除和标记-整理算法。标记-清除 和前文提到的标记一样,与 Scavenge 算法相比,标记清除不会将内存空间划为两半,标记清除在标记阶段会标记活着的对象,而在内存回收阶段,它会清除没有被标记的对象。

而标记整理是为了解决标记清除后留下的内存碎片问题。

增量标记(Incremental Marking)算法

前面的三种算法,都需要将正在执行的 JavaScript 应用逻辑暂停下来,待垃圾回收完毕后再恢复。这种行为叫作“全停顿”(stop-the-world)。

在 V8 新生代的分代回收中,只收集新生代,而新生代通常配置较小,且存活对象较少,所以全停顿的影响不大,而老生代就相反了。

为了降低全部老生代全堆垃圾回收带来的停顿时间,V8将标记过程分为一个个的子标记过程,同时让垃圾回收标记和JS应用逻辑交替进行,直到标记阶段完成。

ad9223555841ab214a9a0daecbac3163.png

经过增量标记改进后,垃圾回收的最大停顿时间可以减少到原来的 1/6 左右。

内存泄漏

内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

内存泄漏的常见场景:

  • 缓存:存在内存中数据一只没有被清掉
  • 作用域未释放(闭包)
  • 无效的 DOM 引用
  • 没必要的全局变量
  • 定时器未清除(React中的合成事件,还有原生事件的绑定区别)
  • 事件监听为清空
  • 内存泄漏优化

7.你熟悉哪些通信协议,它们的优缺点?

通信协议全解

我的这篇文章非常详细介绍了 http1.0 http1.1 http2.0 https websocket等协议

8.从输入url地址栏,发生了什么?由此来介绍如何性能优化:

性能优化不完全手册

如何优化你的超大型React应用

我的这两篇文章基本上涵盖了前端基础的性能优化,后期我会再出专栏。

9.浏览器的缓存实现,请您介绍:

1.preload,prefetch,dns-prefetch等

什么是preload

使用 preload 指令的好处包括:

允许浏览器来设定资源加载的优先级因此可以允许前端开发者来优化指定资源的加载。

赋予浏览器决定资源类型的能力,因此它能分辨这个资源在以后是否可以重复利用。

浏览器可以通过指定 as 属性来决定这个请求是否符合 content security policy。

浏览器可以基于资源的类型(比如 image/webp)来发送适当的 accept 头。

Prefetch

Prefetch 是一个低优先级的资源提示,允许浏览器在后台(空闲时)获取将来可能用得到的资源,并且将他们存储在浏览器的缓存中。一旦一个页面加载完毕就会开始下载其他的资源,然后当用户点击了一个带有 prefetched 的连接,它将可以立刻从缓存中加载内容。

DNS Prefetching

DNS prefetching 允许浏览器在用户浏览页面时在后台运行 DNS 的解析。如此一来,DNS 的解析在用户点击一个链接时已经完成,所以可以减少延迟。可以在一个 link 标签的属性中添加 rel="dns-prefetch' 来对指定的 URL 进行 DNS prefetching,我们建议对 Google fonts,Google Analytics 和 CDN 进行处理。

2.servece-worker,PWA渐进式web应用

PWA文档

6197bc5c18f973d1c994ba3b62d9a422.png

3.localstorage,sessionstorage,cookie,session等。 浏览器的会话存储和持久性存储 4.浏览器缓存的实现机制的实现

efc021458815c602bc695f9f1575e172.png

10.同源策略是什么,跨域解决办法,cookie可以跨域吗?

跨域解决的办法

Q:为什么会出现跨域问题?

A:出于浏览器的同源策略限制,浏览器会拒绝跨域请求。

  • 注:严格的说,浏览器并不是拒绝所有的跨域请求,实际上拒绝的是跨域的读操作。浏览器的同源限制策略是这样执行的:

通常浏览器允许进行跨域写操作(Cross-origin writes),如链接,重定向;

通常浏览器允许跨域资源嵌入(Cross-origin embedding),如 img、script 标签;

通常浏览器不允许跨域读操作(Cross-origin reads)。

Q:什么情况才算作跨域?

A:非同源请求,均为跨域。名词解释:同源 —— 如果两个页面拥有相同的协议(protocol),端口(port)和主机(host),那么这两个页面就属于同一个源(origin)。

Q:为什么有跨域需求?

A:场景 —— 工程服务化后,不同职责的服务分散在不同的工程中,往往这些工程的域名是不同的,但一个需求可能需要对应到多个服务,这时便需要调用不同服务的接口,因此会出现跨域。

方法:JSONP,CORS,postmessage,webscoket,反向代理服务器等。

上篇已经结束,欢迎你关注,等待下篇非常硬核的文章出炉~

期待你加入我们哦~

原文链接:https://segmentfault.com/a/1190

如果喜欢我的文章,想与一群资深开发者一起交流学习的话,获取更多相关大厂面试咨询和指导,欢迎加入我的学习交流群1045267283。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用JavaScript中的setTimeout函数时,如果需要取消定时器,就需要使用clearTimeout函数来清除。否则,定时一直运行,直到达到指定的时间。因此,清除定时器是非常重要的,可以避免不必要的资源浪费和程序错误。 ### 回答2: 在使用JavaScript编写程序的过程中,我们常常需要使用定时器来控制程序中某些操作的执行时间。settimeout就是一种常用的定时器,它可以在指定的时间内延迟执行一段代码,从而实现定时操作。但是,使用settimeout的过程中,我们也需要关注一个问题,那就是是否需要清除。 答案是有必要的。虽然settimeout的作用是在指定的时间后执行一段代码,但是如果我们在定时执行完毕之前清除了该定时器,那么该段代码也将不执行。此外,如果我们先设置了多个定时器,但是没有清除,那么这些定时不断地运行,最终可能导致程序崩溃甚至浏览器崩溃。因此,对于使用settimeout定时器的程序,一定要记得清除定时器。 那么如何清除定时器呢?通过使用clearTimeout函数。这个函数可以取消由settimeout设置的定时器,只需要settimeout函数返回的计时器ID作为参数传入即可。例如,下面的代码就演示了如何设置和清除定时器。 let timer = setTimeout(function(){ console.log('Hello World!'); }, 3000); clearTimeout(timer); 以上代码在3秒钟后输出Hello World,但是由于在settimeout之前立即调用了clearTimeout,因此代码最后不输出任何内容。 总之,JavaScript中settimeout定时器是非常常用的工具,在使用过程中一定要注意正确清除,以避免出现无法预料的问题。 ### 回答3: 在 JavaScript 中,setTimeout() 是一个常见的函数,用于在一定的时间间隔后执行某个任务。它可以用来创建动画效果、延迟代码执行等。但是,在使用 setTimeout() 函数时,有时遇到一些问题,比如任务没有按照预期执行、内存泄漏等,这些问题都可以通过清除 setTimeout() 来避免。因此,一般来说,在需要执行多个任务的情况下,需要及时清除 setTimeout() 函数。 清除 setTimeout() 可以通过 clearTimeout() 函数实现,它可以清除执行的任务,以避免出现意外情况。clearTimeout() 函数需要传递一个参数,这个参数就是待清除setTimeout() 函数的返回值。因此,为了能够正确清除 setTimeout(),需要首先将其返回值保存在一个变量中,然后在需要清除 setTimeout() 的地方,调用 clearTimeout() 并传入保存的返回值即可。 以一个简单的例子来说明清除 setTimeout() 的必要性。比如,下面的代码使用 setTimeout() 来模拟一个简单的弹出窗口: ``` function popup() { alert("Hello World!"); setTimeout(popup, 2000); } setTimeout(popup, 2000); ``` 这里使用 setTimeout() 函数每隔 2 秒钟弹出一个消息框。但是如果用户在关闭消息框的时候点击了其他部分,那么消息框就一直在后台不断弹出,直到占满整个屏幕。这是因为每次 setTimeout() 函数都产生一个新的任务去执行,而旧的任务却没有被清除掉。因此,在这种情况下就需要使用 clearTimeout() 函数来清除旧的任务,避免出现上述问题。 综上所述,当需要执行多个任务时,使用 setTimeout() 函数时建议及时清除,以避免出现一些意外情况。清除 setTimeout() 可以通过 clearTimeout() 函数实现,其参数为待清除 setTimeout() 函数的返回值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值