高性能javascript 筆記(一)

高性能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/WK
			doc = 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.hey
for(var i=0,l=arr.length;i<l;i++){
	console.log(hey)
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章