AI智能
改变未来

高性能javascript读书笔记


页面加载完成后再加载js脚本的方法:

  • defer属性,但存在兼容性问题
  • window.onload 事件函数中动态创建script标签

如何控制js脚本加载的顺序

  • 监听动态脚本的onload事件,在回调中重新加载后续脚本

浏览器加载外部脚本的几种方式?

  • html中静态script标签引入(多文件可通过联合句柄导入,如:
    www.api.com/combo?2.7.0/build/yahoo/yahoo-min.js&2.7.0/build/event/event-min.js

  • 通过js动态创建script标签引入
  • 通过ajax请求js脚本内容,并动态创建script标签后,append至body中

为何箭头函数无法当做构造函数使用

  • 箭头函数的this指向箭头函数本身创建时所处的作用域,并没有指向自身函数作用域的this山下文。所以无法创建确定的对象。
  • 箭头函数同样没有 arguments,super
  • 简写的对象的方法属性就无法用new当做构造函数使用
let a = {tate () {}};new a.tate()  // Error

浏览器中js代码执行引起页面交互卡顿的原因?

  • 浏览器UI线程在,UI渲染和js代码执行中,两者是互斥的,即只有一项可以执行。
  • 为了限制js脚本对资源的抢占, 一些浏览器会做两点限制:
  1. 调用栈的最大长度
  2. js脚本时长(如长时间的setTimeout,或失控的定时器)
  • 使用定时器是js脚本让出对UI线程的控制,优先UI渲染
  • 在定时器中,对js脚本的时长与调用栈限制将会被清零

作用域链模型

  • js在编译阶段通过为每一个函数都添加一个scope的内部属性,该属性为一个数组,从0开始为局部作用域向全局作用域延伸。
  • 作用域链最终态在执行阶段生成
  • with 和 catch 可修改作用域链

何时会发生重排

  • 添加或删除可见的DOM
  • 元素位置改变
  • 元素尺寸改变(边距,填充,边框宽度,宽度,高度等)
  • 内容改变
  • 最初的页面渲染
  • 浏览器窗口的缩放
  • 获取一下dom信息:
// 获取以下信息会使浏览器渲染队列强制刷新后返回最新的数值。所以需要尽可能将以下数据值存放在局部变量中供计算使用offsetTop, offsetLeft, offsetWidth, offsetHeight • scrollTop, scrollLeft, scrollWidth, scrollHeight • clientTop, clientLeft, clientWidth, clientHeight • getComputedStyle() (currentStyle in IE) IE currentStyle

如何减少重排或重绘

  • 多次DOM操作合并为一次DOM操作
  • 离线操作DOM树
  • 减少使用offsetTop等对布局状态的访问,需要多次使用时存放在局部变量中
  • 将动态效果部分使用绝对定位,或放置在固定大小的盒子中展示。
  • 尽量的减少 :hover 触发的动态效果

如何减少重排或重绘在DOM树上的影响范围

  • 动画使用绝对定位,脱离文档流
  • 使动态效果只在固定的节点范围内展示,不影响其他dom元素
  • 在动画的周期结束后,对其他dom元素执行一次重排重绘,而不是随着动画元素的变化持续进行重排或重绘

时间委托

  • DOM事件流的顺序: 捕获阶段, 目标阶段,冒泡阶段
  • 同一个dom上的事件只会被执行一次,可根据addEventListener的第三个参数,选择在捕获阶段执行还是在冒泡阶段执行
<body><div id="obj1">welcome<h5 id="obj2">hello<div id="obj4">obj4</div></h5><h5 id="obj3">world</h5></div><script type="text/javascript">var obj1=document.getElementById(\'obj1\');var obj2=document.getElementById(\'obj2\');var obj4=document.getElementById(\'obj4\');obj1.addEventListener(\'click\',function(){alert(\'welcome\');});obj2.addEventListener(\'click\',function(){alert(\'hello\');}, true)obj2.addEventListener(\'click\',function(){alert(\'obj4\');})// 点击 obj4: hello -> obj4 -> welcome</script></body>

前端 向服务端请求数据的几种方式?

  • ajax
  • 动态js脚本注入
  • iframe
  • image标签
  • form表单

如何提升ajax速度

  • 响应头设置 ajax缓存
  • 基础性的变量本地存储
  • 混合开发 本地localcache
  • cdn节点加速

js 依据 v8引擎的 性能优化

  • 避免使用 eval, with等动态修改运行时上下文的语法
  • 尽可能使用局部变量
  • 遇到大量的字符串拼接时使用数组操作, 因为数组会一次性分配较多的内存,在大量字符串拼接时,就会避免过频繁的内存操作。
  • 尾递归的优化
  • 尽可能减少对象的使用,优先使用字面量,当使用对象时,应尽可能减少在同一作用于对同一对象的多次调用。
function hasEitherClass(element, className1, className2){return element.className == className1 || element.className == className2;}
  • 尽可能将多次dom操作压缩为一次, 尽可能减少重排和重绘;或者说尽可能减少重排或重绘在dom树上的影响范围。
  • 在只需要标签节点时,使用 children 而非 childNodes
  • 优先使用querySelector(返回静态的nodelist)而非 getElementById(返回动态的htmlCollection)
  • 利用事件委托减少DOM事件的绑定
  • 优化循环,如对数组length的多次访问
for (var i=0, len=items.length; i < len; i++){process(items[i]);}* 除非遍历一个未知属性的对象,否则不用for-in循环* 大数据量使用倒序循环,或达夫循环* 优化if else: 最常被命中的判断分支,优先进行判断* 在出现大量条件判断时,尽量使用switch, 在出现巨量判断时候,使用数组或对象进行查表法
  • 通过函数缓存提升性能,空间换时间。例如斐波那契数列的计算
  • 减少临时字符串的使用, 如
    str += "one" + "two";

    =>

    str += "one"; str += "two";
  • 正则表达式的优化
  • 减少js脚本的执行时间1. 大函数拆分后,与定时器结合进行执行2. js任务的批处理3. 将与浏览器UI无关的,高IO和高内存消耗的任务移动至 web worker中
  • 优先使用位运算,如模二运算
  • 使用构建工具,对代码、图片等进行压缩
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 高性能javascript读书笔记