javascript性能

1、浏览器在遇到<body>标签之前,不会渲染页面的任何部分。

如果将<script>标签放在<body>,这种方法把脚本放在页面的顶端,将导致一个可以察觉的延迟,通常表现为:页面打开时,首先显示为一幅空白的页面,而此时用户即不能阅读,也不能与页面进行交互操作。

推荐:将所有的<script>标签放在尽可能接近<body>标签底部的位置

 

2、由于每个<script>标签下载时阻塞页面解析过程,所以限制页面的<script>总数也可以改善性能。

 

非阻塞脚本:

等页面加载完成后,再加载Javascript源码,意思是:在window.onload事件发生后才开始下载源码。

方法1:延期脚本

<script type="text/javascript" src="fileUpload.js"defer></script>

但是只在IE 4+ 和 FF 3.5+才支持。

方法2:动态脚本元素

文档对象模型(DOM)允许使用javascript动态创建HTML的几乎全部文档内容。因为<script>元素与页面中的其它元素没有什么不同。

所以一个<script>可以很容易通过标准DOM创建:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>动态脚本元素</title>
<style type="text/css">
	*{margin:0;padding:0;font-family:微软雅黑}
	span{position:absolute;left:0;top:0}
</style>
</head>

<body>
	<span>测试</span>
</body>

<script type="text/javascript">

	window.onload = function() {
		var jQueryScript = document.createElement("script");
		jQueryScript.type = "text/javascript";
		jQueryScript.src = "jquery-1.9.1.min.js";
		document.getElementsByTagName("head")[0].appendChild(jQueryScript);	
		//不能随即调用jQuery中的方法,我们不知道什么时候能加载完成
		/**IE中可以调用onreadystatechange
		 *<script>有个readyState属性,它随着外部文件的加载过程而改变
		 *1、"uninitialized" :默认状态
		 *2、"loading" :下载开始
		 *3、"loaded" :下载完
		 *4、"interactive" :下载完但是不可用
		 *5、"complete" :所有数据已经准备好
		 *由于<script>加载的过程中,这些状态不一定会都出现,我们只需关系loaded和complete两种状态
		 *考虑到可能不会同时出现,用||即可,为了不让事件重复绑定,当出现其中一种状态时清空readystatechange事件
		*************************************/ 
		jQueryScript.onreadystatechange = function(){
			if(jQueryScript.readyState == "loaded" || jQueryScript.readyState == "complete") {
				jQueryScript.onreadystatechange = null;
				callback();
			}
		}
		//非IE
		jQueryScript.onload = function(){
			callback();
		}
	};
	 
	//当加载完成后就可以调用jQuery中的方法了 
	function callback() {
		jQuery(document).ready(function(){
			$("span").animate({"left":"300px","top":"500px"},5000);
		});
	}
</script>
	
</html>

考虑通用性,可以稍作整理:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/  
xhtml1/DTD/xhtml1-transitional.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />  
<title>动态脚本元素</title>  
<style type="text/css">  
	*{margin:0;padding:0;font-family:微软雅黑}  
	span{position:absolute;left:0;top:0}  
</style>  
</head>  
  
<body>  
	<span>测试</span>  
</body>  
  
<script type="text/javascript">  
	LoadScript = (function(doc){

		var position = doc.getElementsByTagName("body")[0],
			script = doc.createElement("script"),
			script.type = "text/javascript";
		
		//加载js
		function load(url,callback) {
			if(typeof url != "string" || url == null || url == '') {
				alert("加载失败...");
				return ;
			}
			if(script.readyState) {  
				script.onreadystatechange = function(){  
					if(script.readyState == "loaded" || script.readyState == "complete") {  
						script.onreadystatechange = null;  
						callback();  
					}  
				};  
			} else  {  
				script.onload = function(){  
					callback();  
				};  
			}
			script.src  = url;
			position.appendChild(script);
		}	
		
		return {
			js:function(url,callback){
				load(url,callback);
			}
		};
	})(this.document);
	
	LoadScript.js("jquery-1.9.1.min.js",function(){
		$("span").animate({"left":"300px","top":"500px"},5000);  
	});  
</script>  
</html>  

完整写法:参考loadScript.js

调用如:

<script type="text/javascript">
	Require.js(['js/jquery.anchor-1.0.0.js'],function(){jQuery.anchor({layer:$(".yitian-layer")});});
	Require.js(['js/yitian.footer-1.0.0.js'],function(){Yitian.footer.loader({start:2012});});
</script>
可以传入多个参数:

/**
 * javascript 样式,js文件导入
 * @author:xuzengqiang
 * @since :2015-3-12 21:36:08
 * 调用方式:
 * Require.css('index.css',function(){
 *  	//加载完成后的回调函数
 * });
 * Require.js(['js/jquery.anchor-1.0.0.js','js/common.js'],function(){});
**/
var Require = (function(window){
	var document = window.document,
		agent = window.navigator.userAgent.toLowerCase(),
		queue = { //任务队列
			css : [],
			js  : []	
		},
		head = document.head || document.getElementsByTagName("head")[0],
		//目前正在进行的请求
		request = {},
		//轮询总数
		pollCount = 0;

	//全局变量
	window.DOMUtils = {
		//描述:创建一个元素,name:元素名称,attrs:属性集合{id:'content',class:'content'};
		createElement:function(name,attrs){
			var element = document.createElement(name);
			for(var attr in attrs) {
				element.setAttribute(attr,attrs[attr]);
			}
			return element;
		}	
	};
	
	//浏览器信息
	window.Browser = {
		agent: agent,
		isIE : /mise|trident/.test(agent),
		//Gecko内核
		isGecko : agent.indexOf("gecko") > 0 && agent.indexOf("like gecko") < 0,
		//webkit内核
		isWebkit : agent.indexOf("webkit") > 0 
	};
	
	var Load = {
		run : function(type,urls,callback) {
				var isCSS = (type === "css"), //加载类型,只考虑js和css
					node,current; //节点 				
				if(urls) {
					//concat()用于连接数组,但是不会改变现有数组,只是返回被连接数组的一个副本
					urls = typeof urls === 'string' ? [urls] : urls.concat();
					//除了Firefox和Opera浏览器能够保证并行加载且能保留顺序执行,所以统一按顺序将任务加入到任务队列中
					for(var i=0,maxLen = urls.length;i<maxLen;i++) {
						queue[type].push({
							url : urls[i],
							callback : (i === maxLen-1)? callback : null //当有多个等所有资源加载完成后才调用callback
						});	
					}
				}
				
				//如果资源加载完成
				if (request.type || !(current = request.type = queue[type].shift())) {
					return false;
				}
				
				if(isCSS) {
					//火狐下不支持link标签的onload事件.所以创建style标签,通过@import引入样式
					node = Browser.isGecko?DOMUtils.createElement("style"):DOMUtils.createElement("link",{
							type:'text/css',rel:'stylesheet',href:current.url});
				} else {
					node = DOMUtils.createElement("script",{type:'text/javascript',src:current.url});
					//同步加载,防止顺序错乱
					node.async = false;
				}
				node.className="require";
				node.setAttribute("charset","utf-8");
				
				//IE浏览器且不是CSS文件
				if(Browser.isIE && !isCSS && node.onreadystatechange) {    
					node.onreadystatechange = function(){    
						if(/loaded|complete/.test(node.readyState)) {    
							node.onreadystatechange = null;    
							Load.complete(type);
						}    
					}; 
				//webkit内核和gecko内核不支持link节点的onload方法,document.getElementsByTagName("link")[0].onload
				} else if(isCSS && (Browser.isWebkit || Browser.isGecko)) {
					 if (Browser.isWebkit) {
						  //current.url = node.href; // 解决相对url(或轮询不会工作)
						  Load.pollWebkit(type);
					 } else {
						  node.innerHTML = '@import "' + current.url + '";';
						  Load.pollGecko(node);
					 }
				} else  {    
					node.onload = node.onerror = function(){
						Load.complete(type);
					};  
				}  
				
				head.appendChild(node);
			},
			complete:function(type){
				var req = request.type,callback;
				//如果有请求
				if(req) {
					callback = req.callback;
					pollCount = 0;
					// 如果为最后一个待加载的URL 执行回调并且开始下一个队列中的请求(如果有)
				  	if (req.url !== null) {
						if(typeof callback !== 'undefined' && callback !== null) {
							callback();
						}
						request.type = null;
						queue[type].length && Load.run(type);// 队列中如还有当前类型的资源 加载该类型资源
				  	}
				}
			},
			//轮询判断样式是否已经加载完成,样式加载完成后或10s后停止轮询
			pollWebkit:function(type){
				var css = request.type, len, styleSheets = document.styleSheets;
 				if (css !== null) {
      				len = styleSheets.length;
 					//遍历styleSheets判断是否加载完毕
      				while (--len >= 0) {
        				if (styleSheets[len].href === css.url) {
          					Load.complete('css');
          					break;
        				}
      				}
					pollCount += 1;
 					if (css !== null) {
        				if (pollCount < 200) {
          					setTimeout(function(){Load.pollWebkit(type);}, 50);
        				} else {
          					Load.complete('css');
        				}
      				}
    			}
			},
			//内核为Gecko的浏览器轮询
			pollGecko:function(node){
				var hasRules; //是否已经加载完成
 				try { 
			    	hasRules = !!node.sheet.cssRules;
				} catch (ex) {
					// 样式表仍然是在加载...那么轮询10秒,超过10s,退出
					pollCount += 1;
				 	if (pollCount < 200) {
						setTimeout(function () { Load.pollGecko(node); }, 50);
					} else {
						hasRules && Load.complete('css');
					}
				 	return false;
				}
				Load.complete('css');
			}
		};
	
	return {
		css:function(urls,callback) {
			return Load.run("css",urls,callback);	
		},
		js:function(urls,callback) {
			return Load.run("js",urls,callback);	
		}
	}
})(window);





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值