[JavaScript初级面试]17. 运行环境 - 性能优化

原则 -- 用空间换时间

  • 多使用内存,缓存
  • 减少CPU计算量,减少网络的加载耗时

目标

  • 加载更快
    减少资源体积:压缩代码,图片:利用打包工具
    减少网络访问次数:合并代码,SSR服务器端渲染,缓存

a.js b.js c.js => abc.js

服务器端渲染:将网页和数据一起加载,一起渲染
非SSR:先加载网页,再加载数据,再渲染数据

静态资源加hash后缀,根据文件内容计算hash
文件内容不变,hash不变,则url不变
url和文件不变,则会出发http缓存机制,返回304

使用更快的网络:CDN

  • 渲染更快
    CSS放在header,JS放在body最下面
    尽早开始执行JS,用DOMContentLoaded触发
    懒加载(图片懒加载,分页)
// 开始建在较小的预览图片,真实图片地址放在data-realsrc中
<img id="img1" src="preview.png" data-realsrc="abc.png"/>
<script>
  // DOM加载完成后,再把真实图片加载出来
  var img1 = document.getElementById('img1')
  img1.src = img1.getAttribute('data-realsrc')
</script>

对DOM查询进行缓存
频繁的DOM操作,合并到一起插入DOM结构

防抖(debounce)
场景:监听一个输入框change事件,如果用keyup会频发出发change事件
用户输入结束或暂停时,才会触发change事件,就是防抖

const input1 = document.getElementById('input1')
let timer = null
input1.addEventListener('keyup', function(){
  if(timer){
    clearTimeout(timer)
  }
  timer = setTimeout(() => {
    console.log(input1.value) // 模拟触发change事件
    timer = null // 清空定时器
  }, 500)
})

封装为debounce函数:

function debounce(fn, delay = 500){
  let timer = null // 自由变量
  return function(){
    if(timer)
      clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, arguments)
      time = null
    }, delay)
  }
}

input1.addEventListener('keyup', debounce(()=>{
  console.log(input1.value) // 箭头函数中,使用input1可以正确获取input1对象
  // 如果现在箭头函数中,使用this.value打印的并不是input1的value,而是window.value
  // 如果想动态指定this的值,此时就需要把箭头函数改为function,并在debounce函数中绑定事件触发时,this的值
}, 500))

节流(throttle)
场景:拖拽一个元素时,要随时拿到该元素被拖拽的位置;
直接用drag事件,则会频繁触发,很容易造成卡顿

节流:无论拖拽速度多快,都会每个100ms触发一次

<div id="div1" draggable="true">
可拖拽
</div>
<script>
const div1 = document.getElementById('div1')
div1.addEventListener('drag', (e)=>{
   console.log(e.offsetX, e.offsetY) //频繁打印位置
})
</script>

改良 ==> 节流

const div1 = document.getElementById('div1')
let timer = null
div1.addEventListener('drag', (e)=>{
   if(timer)
     return
   timer = setTimeout(() => {
     console.log(e.offsetX, e.offsetY)
     timer = null
   }, 100)
})

改良 函数 ==> 节流

function throttle(fn, delay = 100){
  let timer = null
  return function(){
    if(timer)
      return
    timer = setTimeout(() => {
      fn.apply(this, arguments) // arguments把div1注册的函数参数传入入
      timer = null
    }, delay)
  }
}

div1.addEventListener('drag', throttle(function(e){
  console.log(e.offsetX, e.offsetY)
}, 200))
posted @ 2021-09-06 22:02  Max力出奇迹  阅读(61)  评论(0编辑  收藏  举报
返回顶部↑