JS编程中高性能注意点
1. 用局部变量存储本地范围之外的变量值,如果它们在函数中的使用多于一次。
2. 实例成员与原型成员的关系hasOwnProperty
3. 一般来说,将经常使用的对象成员,数组项,和域外变量存入局部变量中。然后访问局部变量的速度会快于那些原始变量;
Dom操作:
1. 访问Dom次数越多,代码执行速度越慢。因此一般都是尽量少的查询修改dom元素
2. Dom集合存在length,建议将length值缓存在变量中,然后在循环中使用
3. 如果同一个DOM属性或者方法被访问一次以上,最好使用一个局部变量缓存此DOM成员。
4. 减少重绘重排的次数,应该将多个DOM和风格改变合并到一个批次中一次执行
1)css类代替内联
2)使用代码片段或者隐藏显示方式,引发一次重排版---只触发存在DOM一次
异步请求方面:
1. 浏览器可以支持6个请求并发执行,所以对于异步请求数据,尽量并发执行
2. 对于异步请求的数据,可以进行缓存处理
3. 如果对于大量计算的可以启用webWorker技术
4. 如果WebWorker还不能满足,则加入WebAssimbly技术
编程注意点:
1. 当判断条件较多时,查表法比if-else或者switch更快
function memfactorial(n){ if(!memfactorial.cache){ memfactorial.cache = { "0": 0, "1": 1 }; } if(!memfactorial.cache.hasOwnProperty(n)){ memfactorial.cache[n] = n * memfactorial(n-1); } return memfactorial.cache[n]; } function memoize(fundamental, cache){ cache = cache || {}; let shell = function(arg){ if(!cache.hasOwnProperty(arg)){ cache[arg] = fundamental(arg); } return cache[arg]; }; return shell; }
2. 字符串操作
1)链接字符串的时候避免重复的内存分配和拷贝越来越大的字符串。
2)使用连接数组连接代替直接字符串的连接操作;
3)concat的性能不如直接+
编程复杂度常识
1. 控制JavaScript任务在100毫秒内完成,如果因为复杂不能在100毫秒内完成,最理想的方式是让出UI线程的控制,使UI更新可以进行。
button.onClick = function(){ onMethod(); setTimeout(function(){ document.getElementById("notice").style.color = "red"; }, 250); anotherMethod(); }; 通常一个定时器最小设置为25毫秒
2. 数组中处理定时器
function processArray(items, process, callback){ let todo = items.concat(); setTimeout(function(){ process(todo.shift()); if(todo.length > 0){ setTimeout(arguments.callee, 25); }else{ callback(items); } }, 25); }
3. 分解任务
function saveDocument(id){ let tasks = [openDocument, writeText, closeDocument, updateUI]; setTimeout(function(){ let task = tasks.shift(); task(id); if(tasks.length > 0){ setTimeout(arguments.callee, 25); } }, 25); }
封装: function multistep(steps, args, callback){ let tasks = steps.concat(); setTimeout(function(){ let task = tasks.shift(); task.apply(null, args || []); if(tasks.length > 0){ setTimeout(arguments.callee, 25); }else{ callback(); } }, 25); } function saveDocument(id){ let tasks = [openDocument, writeText, closeDocument, updateUI]; multistep(tasks, [id], function(){ console.log("Done"); }); }
定时器中添加时间检测机制,让每个定时器执行多次处理-----避免将任务分解成过小的碎片 function timeProcessArray(items, process, callback){ let todo = items.concat(); setTimeout(function(){ let start = +new Date(); do{ process(todo.shift()); }while(todo.length > 0 && (+new Date() - start) < 50); if(todo.length > 0){ setTimeout(arguments.callee, 25); }else{ callback(items); } }, 25); }
4. Web Worker
例如:解析一个很大的JSON字符串,至少需要500毫秒
let worker = new Worker("jsonparser.js"); worker.onmessage = function(event){ let jsonData = event.data; evaluateData(jsonData); }; worker.postMessage(jsonText); //jsonparser.js self.onmessage = function(event){ let jsonText = event.data; let jsonData = JSON.parse(jsonText); self.postMessage(jsonData); }
Ajax
1.当使用XHR请求数据时,你可以选择POST或者GET。如果请求不改变服务器状态只是取回数据(又称幂等动作)则使用GET,因为GET请求会被缓存起来。多次请求可以提高性能。
2. 或者URL长度超过2048时使用POST取数据
3. 动态脚本标签插入该技术克服了XHR的最大限制:他可以从不同域的服务器上获取数据
4. 失败重试
function xhrPost(url, params, callback){ let req = new XHLHttpRequest(); req.onerror = function(){ setTimeout(function(){ xhrPost(url, params, callback); }, 1000); }; req.onreadystatechange = function(){ if(req.readyState === 4){ if(callback && typeof callback === "function"){ callback(); } } }; req.open('POST', url, true); req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); req.setRequestHeader('Content-Length', params.length); req.send(params.json('&')); }
灯标技术????