页面加载完成后再加载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脚本对资源的抢占, 一些浏览器会做两点限制:
- 调用栈的最大长度
- 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中
- 优先使用位运算,如模二运算
- 使用构建工具,对代码、图片等进行压缩