上一篇链接:2019年一些前端的面试题(含答案)
7、手写函数防抖和函数节流
函数节流
函数节流是让这个函数在间隔某一段时间执行一次
以输入框为例,假设你想查询xxxx,你想实现当我开始输入多少秒之后,执行查询操作。(并不一定要输入完毕)
核心是去判断当前时间和开始时间的间隔是否到达了设置的delay值,如果达到了,就执行一次回调。没有则不执行。
函数防抖
让这个函数在执行上一次之后过了你规定的时间再执行的一种方法
核心在于每次都去clear一个延时器,然后每次执行函数的时候,都去clear以前的延时器。只有当你中断输入的时候,才会去执行相应回调。
function throttle(method,context){
clearTimeout(method.tId)
method.tId = setTimeout(function(){
method.call(context)
},1000)
}
封装节流和防抖,通过第三参数来切换模式
const throttle = function(fn, delay, isDebounce) {
let timer
let lastCall = 0
return function (...args) {
if (isDebounce) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn(...args)
}, delay)
} else {
const now = new Date().getTime()
if (now - lastCall < delay) return
lastCall = now
fn(...args)
}
}
}
8、浏览器渲染过程
一图胜千言
- 浏览器使用HTTP协议或者HTTPS协议,向服务端请求页面
- 把请求回来的HTML代码经过解析,构建成DOM树
- 计算DOM树上的CSS属性
- 根据CSS属性对元素逐个渲染,得到内存中的位图
- 中间可能包括对位图进行合成,极大地增加后续绘制的速度
- 合成后,在绘制到界面上
9、回流重绘是什么?
HTML默认是流式布局的,但CSS和JS会打破这种布局,改变DOM的外观样式以及大小和位置。
reflow(回流)
当浏览器发现某个部分发生了变化从而影响了布局,这个时候就需要倒回去重新渲染
几乎是无法避免的,因为只要用户进行交互操作,就势必会发生页面的一部分的重新渲染,且通常我们也无法预估浏览器到底会reflow哪一部分的代码,因为他们会相互影响。
- display:none是回流
减少回流的方式
- 用transform做形变和位移.
- 通过绝对位移来脱离当前层叠上下文,形成新的Render Layer。
repaint(重绘)
当我们改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸和位置没有发生改变。
- visibility: hidden是重绘
10、图片懒加载怎么实现的?
先将img标签中的src链接设为同一张图片(空白图片),将其真正的图片地址存储再img标签的自定义属性中(比如data-src)。当js监听到该图片元素进入可视窗口时,即将自定义属性中的地址存储到src属性中,达到懒加载的效果。
var viewheight = document.documentElement.clientHeight //可视区域高度
function lazyload(){
var eles = document.querySelectorAll('img[data-original][lazyload]')
Array.prototype.forEach.call(eles,function(item,index){
var rect;
if(item.dataset.original === '') return;
rect = item.getBoundingClientRect(); //返回元素的大小及其相对于视口的
if(rect.bottom >= 0 && rect.top < viewheight){
!function(){
var img = new Image();
img.src = item.dataset.url;
img.onload = function(){
item.src = img.src
}
item.removeAttribute('data-original');
item.removeAttribute('lazyload');
}()
}
})
}
11、vue-lazyloader的原理
一图胜千言
- vue-lazyload是通过指令的方式实现的,定义的指令是v-lazy指令
- 指令被bind时会创建一个listener,并将其添加到listener queue里面, 并且搜索target dom节点,为其注册dom事件(如scroll事件)
- 上面的dom事件回调中,会遍历 listener queue里的listener,判断此listener绑定的dom是否处于页面中perload的位置,如果处于则加载异步加载当前图片的资源
- 同时listener会在当前图片加载的过程的loading,loaded,error三种状态触发当前dom渲染的函数,分别渲染三种状态下dom的内容
原文链接,很详细的源码解析:Vue-lazyload原理详解之源码解析
12、websocket握手过程
webstocket是html5的一种新的协议,是一个持久化的协议,相对于HTTP这种非持久的协议来说。它实现了浏览器与服务器的双向通道,使得数据可以快速的双向传播
通过一次简单的握手,建立了客户端和服务器的联系后,服务器可以主动推送信息给客户端,而不需要客户端的反复请求
优点
- 客户端和服务器端之间数据交流的表头比较小。大概2个字节
- 服务器和客户端可以主动的发送数据给对方
- 不需要有频率的创建TCP请求和销毁,节约宽带和服务器的资源
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
// 一个Base64 encode的值,这个是浏览器随机生成的
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
// 一个用户定义的字符串,用来区分同URL下,不同的服务所需要的协议
Sec-WebSocket-Protocol: chat, superchat
// 告诉服务器所使用的Websocket Draft(协议版本)
Sec-WebSocket-Version: 13
Origin: http://example.com
服务器会返回下列东西
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
// 经过服务器确认,并且加密过后的 Sec-WebSocket-Key
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
// 表示最终使用的协议
Sec-WebSocket-Protocol: chat
表示已经接受到请求, 成功建立Websocket啦!