高性能javascript 笔记(一)

来源:互联网 发布:思科解绑mac地址 编辑:程序博客网 时间:2024/04/29 20:27
高性能javascript 笔记(一)

加载和执行

阻塞脚本

<script>标签 在加载的时候会阻塞其他资源的加载.这个我以前知道,但是不知道为什么为阻塞,原因如下
无论是内嵌的scirpt还是引用外部的js,页面的下载和解析过程必须停下,等待脚本完成这些处理,然后才能继续。这是页面生命周期必不可少的部分,因为脚本可能在运行过程中修改页面内容。典型的例子是document.write()函数

代码如下

      <html>            <head>                  <title>Script Example</title>            </head>            <body>                  <p>                  <script type="text/javascript">                        document.write("The date is " + (new Date()).toDateString());                  </script>                  </p>            </body>      </html>
正如上面HTML 页面中那样,无法预知JavaScript 是否在<p>标签中添加内容。因此,浏览器停下来,运行此JavaScript 代码,然后再继续解析、翻译页面。同样的事情发生在使用src 属性加载JavaScript 的过程中。浏览器必须首先下载外部文件的代码,这要占用一些时间,然后解析并运行此代码。此过程中,页面解析和用户交互是被完全阻塞的。

所以<script>标签应该是放在页面的下面,因为放上面要等待js下载完并且执行完了,才会去渲染界面
Internet Explorer 8, Firefox 3.5, Safari 4, 和Chrome 2 允许并行下载JavaScript 文件。这个好消息表明,当一个<script>标签正在下载外部资源时,不必阻塞其他<script>标签。不幸的是,JavaScript 的下载仍然要阻塞其他资源的下载过程,例如图片。
上面的话是从书上抄的,在chorme下去,发现js 图片 资源是可以并行在下的.chrome v5啊

动态脚本元素

这个以前有看,但是没有深入了解过,所以做些笔记

动态创建的script标签是在下载的时候是不会阻塞其他资源下载和渲染的,这是他的好处.坏处就是不好控制什么时候完成了加载

一般创建一个script标签,

非ie下  用script.onload来捕获是否完成了标签的加载

ie下  用 script. onreadystatechange 监听 script.readyState 为loaded或者为 complete的时候表示标签加载完成(这个2动作可能有时候去触发一个,有时候会都触发,所以当触发了其中的一个的时候,吧这个事件从scipt上去掉,避免第2次触发)

一个例子

<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><link rel="Stylesheet" type="text/css" href="http://common.cnblogs.com/css/reset.css" /><style type="text/css">*{margin:0;padding:0;}</style><title></title></head><script type="text/javascript">if(!window.console){window.console = {"log" : function(txt){alert(txt)}}}function createJsCss(url,callback){if(!/[a-z0-9]\.js$/i.test(url)){return false;}if(!callback || typeof callback != "function"){callback = function(){};}var script = document.createElement("script");script.type = "text/javascript";script.src = url;if(script.readyState){script.onreadystatechange = function(){if(script.readyState == "loaded" || script.readyState == "complete"){script.onreadystatechange = null;callback();script = null;}}}else{script.onload = function(){callback();}}document.getElementsByTagName("head")[0].appendChild(script);}createJsCss("http://common.cnblogs.com/script/jquery.js",function(){console.log("load!!!")});</script><body><h1>创建js标签  因为可以不阻塞</h1><img src="http://img02.taobaocdn.com/bao/uploaded/i2/T13ZDeXfNsXXXOjLs1_041123.jpg"><br>    <img src="http://img04.taobaocdn.com/bao/uploaded/i4/13444019606750826/T1antaXqteXXXXXXXX_!!0-item_pic.jpg"><br></body></html>

这个是js的,外部资源还有css,不过link标签比较悲剧,FF/Webkit都不支持onload,onreadystatechange,在link标签下用node的标签的node.sheet.cssRules来看它样式的长度表示它加载完了(这个不能跨域引用)

一个例子

<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title></title></head><script type="text/javascript">if(!window.console){window.console = {"log" : function(txt){alert(txt)}}}function createJsCss(url,callback){var isurl = /[a-z0-9]\.(js|css)$/i.exec(url);if(isurl == null){return false;}if(!callback || typeof callback != "function"){callback = function(){};}var iscss = isurl[1] =="css",sniff = 1 + /(?:Gecko|AppleWebKit)\/(\S*)/.test(navigator.userAgent), // 0 - IE, 1 - O, 2 - GK/WKdoc = document,head = doc.head || doc.getElementsByTagName("head")[0],node,createNode = function(name, attrs){var node = doc.createElement(name), attr;for (attr in attrs) {if (attrs.hasOwnProperty(attr)) {node.setAttribute(attr, attrs[attr]);}}return node;}if(iscss){node = createNode("link",{type : "text/css",rel  : "stylesheet",href : url});}else{node = createNode("script",{type : "text/javascript",url  : url});}node.setAttribute('charset', 'utf-8');this.xx = node;if(iscss){if(sniff == 2){!function (){var my = arguments.callee;if(node.sheet && node.sheet.cssRules){callback();}else{setTimeout(my,200);}}();}else{node.onload = function(){callback();}}}else{if(node.readyState){script.onreadystatechange = function(){//if(script.readyState == "loaded" || script.readyState == "complete"){if(/loaded|complete/.test(script.readyState)){script.onreadystatechange = null;callback();script = null;}}}else{script.onload = function(){callback();}}}head.appendChild(node);}//createJsCss("http://common.cnblogs.com/script/jquery.js",function(){console.log("load!!!")});createJsCss("reset.css",function(){console.log("load!!!")});</script><body><!--<img src="http://img02.taobaocdn.com/bao/uploaded/i2/T13ZDeXfNsXXXOjLs1_041123.jpg"><br>    <img src="http://img04.taobaocdn.com/bao/uploaded/i4/13444019606750826/T1antaXqteXXXXXXXX_!!0-item_pic.jpg"><br>--></body></html>

数据访问

数据的存储位置会在很大的程度上影响读取速度,javascript里面也一样,js只有四中存储方案,直接量,变量,数组,对象成员。读取速度

什么是直接量了 如下

var a = "asdf";a.split(""); //这里就是变量"asdf".split("");//这里就是直接量了

直接量,变量读写消耗很少,数组,对象消耗较多

还有一个就是作用域了,当前的作用域下的变量肯定比 其他作用域下的变量要快,(高性能javascript 里面的作用域讲的非常好了,推荐看),而且标示符所在的位置越深,它的读写速度越慢,所以拿一个全局变量引用更深层次的变量,是个好方法

闭包变量(暂且这么叫),它是会一直占着内存的,而且GC不会回收,好处就是可以提高访问速度

对象的属性查找 比如a.b,它是会查找所有的a下的属性,所以这个也不能滥用啊,像这种嵌套的也拿变量保存起来用吧,一般2次以前的嵌套对象就可以拿一个变量来保存了(其实我写代码中,一直遵循这个原则,特别是在遍历当中,把嵌套的变量提出来很有必要)

一个例子

var comm =  {options : {hey : "hey,I miss you",arr : ["rain now"]}}alert(comm.options.hey)alert(comm.options.arr.join(""))// 如果多次使用 comm.options  肯定拿个变量保存比较好var options = comm.options;alert(options.hey)alert(options.arr.join(""))

遍历中更为重要

var comm = {a:{hey : "hey,I miss you"}}var arr = [1,2,3,4,5,6,7,8,9]for(var i=0,l=arr.length;i<l;i++){console.log(comm.a.hey)}// 遍历中取变量的值的时候  一定要把变量提出来啊var arr = [1,2,3,4,5,6,7,8,9],hey = comm.a.heyfor(var i=0,l=arr.length;i<l;i++){console.log(hey)}