程序算法和流程优化,包括优化循环、递归等等
for-in循环所返回的对象包括实例属性和从原型链中继承的属性,它是四种循环中最慢的,大约只有其他类型速度的1/7; 2. 优化循环有两种方式: 减少迭代工作量 ->复杂度=0(n)时首选 减少迭代次数 ->复杂度>0(n)时首选 3. 减少迭代工作量方法: 在初始化中将length保存为局部变量,例如:for(let i=0, len=arr.length; i<len; i++) 使用倒序循环,例如:for(let i=10;i--;){},while(j--){},每次循环减少一次控制条件判断(迭代次数少于上限?值是否为true?=>值是否为true?); 4. 减少迭代次数方法: “达夫设备”,每次循环执行多次操作,在迭代次数>1000时考虑使用; 5. 大多数情况switch比if-else更快,但只要当条件数量很大时才慢得明显。因为大多数语言对switch采用分支表索引进行优化,并且在js中在switch中使用全等操作符,不会发生类型转换; 6. 条件语句选择: 离散值 => switch 多个值域 => if-else 大量离散值且条件和值存在映射关系 => 查找表(存入数组直接return) 7. 优化if-else方法:最可能出现的条件放在首位,嵌套if-else(二分法); 8. 除IE的调用栈是与系统空闲内存有关,其他浏览器都有固定数量的调用栈限制;
浏览器调用栈错误提示错误类型IEStack overflow at line x常规ErrorFirefoxToo much recursionInternalErrorSafariMaximum call stack size exceededRangeErrorChrome不提示RangeErrorOperaAbort(control stack overflow)终止js引擎,不抛出错误9. 两种递归模式:直接递归模式、隐伏模式;
字符串操作优化和正则表达式查找优化,包括优化字符串连接、正则匹配等等
使用各种技术提升应用交互性,包括合理管理UI线程、使用Web Worker进行额外计算等等
4. 单个js操作花费总时间不应该超过100ms; 5. 有些浏览器在js运行期间不会把UI更新任务加入队列,这是为了保证UI页面的动态变化,所以可能出现脚本运行期间点击按钮,无法看到它被按下的样式,但它的onlick事件处理器会被执行; 6. 使用定时器管理UI线程: - 定时器从调用它时开始算,计时完成后被加入UI队列,但需要注意函数只有在创建它的函数执行完成之后才有可能被执行 - 定时器会重置所有相关的浏览器限制,包括长时间运行脚本定时器,调用栈也会重置为0 - js定时器通常不太精确,相差大约几毫秒。因为例如windows系统定时器分辨率是15ms,即一个15ms的定时器会根据最后一次系统时间刷新而转换为0或15。最小值最好为25ms(实际时间15或30)以确保至少有15ms的延时,再小的延时对大多数UI更新会不够用 7. 记录代码运行时间:
var start = +new Date(), stop; process(); stop = +new Date(); var time = stop - start; 当任务与UI无关且不能被分解时可考虑使用Worker Web Worker运行环境: navigator,包含属性:appName、appVersion、user Agent、platformlocation,只读self,指向全局worker对象importScripts(),用来加载外部js文件,阻塞式,直到执行完成才继续所有ES对象,Object、Array、Date等XMLHttpRequestsetTimeout()、setInterval()close(),终止Worker运行使用Worker需要单独建立js文件然后使用:var worker = new Worker('code.js'),文件会异步下载,文件下载执行完成后才会启动此Worker;主进程端: var worker = new Worker('code.js'); worker.onmessage = function(e) { console.log(e.data); } worker.postMessage("s");Worker端:
self.onmessage = function(e) { self.postMessage(e.data); }使用各种技术提升应用交互性,包括合理管理UI线程、使用Web Worker进行额外
1 向服务器请求数据的常用技术: - XHR - 动态脚本注入 - Multipart XHR - iframes - Comet 2 GET请求具有幂等性,对服务器无副作用,经GET请求的数据会被缓存起来; 3 IE限制URL长度,当URL长度超过2048个字符(4k)时应使用POST; 4 可以使用“流”分段处理返回数据,低版本IE不支持“流”,也不提供readyState为3的状态; 5 使用动态脚本注入有很多限制,包括不能设置请求头,只能用GET,不能设置请求超时或重试,必须等所有数据返回才能访问等等,实现JSONP(JSON with padding)跨域:
//js端 var scriptEle = document.createElement('script'); scriptEle.src = "url"; document.getElementsByTagName('head')[0].appendChild(scriptEle); function callBack(jsonString) { var data = eval('(' + jsonString + ')'); } //服务端返回 callBack({"status":1, "data": 2});6 可以将参数以var params = ['key1=value1','key2=value2']格式存为数组,最后params .join(‘&’)拼接; 7 GET只发送一个数据包,而POST至少发送两个(请求头、请求正文),所以GET请求速度会更快; 8 向服务器发送数据技术:XHR、Beacons(信标) 9 Beacons实例:(new Image()).src = url + '?' + params .join('&'); 是给服务器回传信息最有效的方式,性能消耗小且服务端错误不会影响客户端; 接收服务器返回数据:监听Image对象的load事件;检查服务器返回图片的宽高(如可以用宽1表示成功,2表示重试); 10 XML优点: - 极佳的通用性,服务端和客户端都完美支持 - 格式严格 - 易于验证 但也存在过于冗长,语法模糊的问题,解析它也需要提前知道它的结构 11 XHR获取的JSON是字符串格式,而JSON-P本身就被当做JSON对象; 12 两种情形避免使用JSON-P,因为JSON-P必须是可执行js,可能被任何人调用并使用动态脚本注入技术插入任何网站;不能把敏感数据编码在JSON-P中,因为你无法确认它是否保持私有调用状态,即使带有随机URL和做了cookie判断; 13 最快的ajax请求就是没有请求,减少不必要请求方法: - 服务端,设置HTTP头信息确保响应被浏览器缓存(设置Expires头信息,GMT日期格式) - 客户端,把获取的信息存储到本地,避免再次请求 14 大多数浏览器支持XMLHttpRequest对象,老版本浏览器使用ActiveX对象,并需要传入版本号,通用获取xhr对象方法:
function createXhrObject(){ var msxml_progid = [ 'MSXML2.XMLHTTP.6.0', 'MSXML3.XMLHTTP', 'Microsoft.XMLHTTP', //不支持readyState 3 'MSXML2.XMLHTTP.3.0', //不支持readyState 3 ]; var req; try{ req = new XMLHttpRequest(); } catch(e){ for(var i = 0, len = msxml_progid.length; i<len; i++){ try{ req = new ActiveXObject(msxml_progid[i]); break; } catch(e2){} } } finally{ return req; } }15 各种交互手段比较: - XML支持良好,但笨重且解析缓慢;JSON轻量级解析快,但需要编写额外的服务端构造程序; - 动态脚本注入允许跨域请求和本地执行js和JSON,但它的接口不安全,而且不能读取头信息或响应代码; - Multipart XMR可以减少请求数并处理一个响应中的各种文件类型,但不能缓存接收到的响应
一些编程中需要注意的优化细节,包括条件预加载、使用底层方法等等。
1 传入字符串并动态执行的方法:eval()、Function()构造函数、setTimeout()、setInterval(); 2 每次调用eval()都要创建一个新的解释器实例; 3 避免重复的条件判断:延迟加载、条件预加载 当一个函数在页面中不会立刻调用时,延迟加载是最好的选择:
function addHandler(target, eventType, handler){ if(target.addEventListener){ //复写函数 addHandler = function(target, eventType, handler){ target.addEventListener(eventType, handler, false); } }else{ addHandler = function(target, eventType, handler){ target.attachEvent("on" + eventType, handler); } } //调用新函数 addHandler(target, eventType, handler); }条件预加载:函数定义时判定
var addHandler = document.body.addEventListener? function(target, eventType, handler){ target.addEventListener(eventType, handler, false); }: function(target, eventType, handler){ target.attachEvent("on" + eventType, handler); } }4 js引擎是由低级语言构建的而且经过编译,使用位操作符和原生方法例如Math中的方法和querySelectorAll()速度更快; 5 位操作符应用:i&1可以判断奇偶,奇时返回true,偶时返回false