JS代码优化小技巧
下面介绍一种JS代码优化的一个小技巧,通过动态加载引入js外部文件来提高网页加载速度
-
【基本优化】
将所有需要的<script>标签都放在</body>之前,确保脚本执行之前完成页面渲染而不会造成页面堵塞问题,这个大家都懂的。

-
【合并JS代码,尽可能少的使用script标签】
最常见的方式就是带代码写入一个js文件中,让页面只使用一次<script></script>标签来引入

-
【无堵塞加载JS】
通过给script标签增加 defer属性或者是 async 属性来实现
<script src="file.js" defer></script>
注解:
async和defer不同之处是async加载完成后会自动执行脚本,defer加载完成后需要等待页面也加载完成才会执行代码

-
【动态创建script来加载-推荐】
function loadJS( url, callback ){
var script = document.createElement('script'),
fn = callback || function(){};
script.type = 'text/javascript';
//IE
if(script.readyState){
script.onreadystatechange = function(){
if( script.readyState == 'loaded' || script.readyState == 'complete' ){
script.onreadystatechange = null;
fn();
}
};
}else{
//其他浏览器
script.onload = function(){
fn();
};
}
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}
//用法
loadJS('file.js',function(){
alert(1);
});

-
谷歌浏览器运行效果,script被动态创建在head中


-
建议大家可以封装成类库,单独引入。
该原理实现的也有很多不错的js类库可以使用,如LazyLoad.js,支持数组的形式引入,打开浏览器在network中可看到js是同步加载的


-
【XHR加载】
使用ajax方式加载
代码:
var xhr = new XMLHttpRequest;
xhr.open('get','file.js',true);
xhr.onreadystatechange = function(){
if( xhr.readyState == 4 ){
if( xhr.status >=200 && xhr.status < 300 || xhr.status == 304 ){
var script = document.createElement('script');
script.type = 'text/javascript';
script.text = xhr.responseText;
document.body.appendChild(script);
}
}
};
xhr.send(null);
JS常用扩展:
if (!Array.isArray) { Array.isArray = function(arg) { return Object.prototype.toString.call(arg) === '[object Array]'; }; } if (!Array.prototype.forEach) { Array.prototype.forEach = function (callback/*, thisArg*/) { var T, k; if (this == null) { throw new TypeError('this is null or not defined'); } // 1. Let O be the result of calling toObject() passing the // |this| value as the argument. var O = Object(this); // 2. Let lenValue be the result of calling the Get() internal // method of O with the argument "length". // 3. Let len be toUint32(lenValue). var len = O.length >>> 0; // 4. If isCallable(callback) is false, throw a TypeError exception. // See: /#x9.11 if (typeof callback !== 'function') { throw new TypeError(callback + ' is not a function'); } // 5. If thisArg was supplied, let T be thisArg; else let // T be undefined. if (arguments.length > 1) { T = arguments[1]; } // 6. Let k be 0. k = 0; // 7. Repeat while k < len. while (k < len) { var kValue; // a. Let Pk be ToString(k). // This is implicit for LHS operands of the in operator. // b. Let kPresent be the result of calling the HasProperty // internal method of O with argument Pk. // This step can be combined with c. // c. If kPresent is true, then if (k in O) { // i. Let kValue be the result of calling the Get internal // method of O with argument Pk. kValue = O[k]; // ii. Call the Call internal method of callback with T as // the this value and argument list containing kValue, k, and O. callback.call(T, kValue, k, O); } // d. Increase k by 1. k++; } // 8. return undefined. }; } //生成生肖、星座 var Calculator = function () { /* * * 计算生肖 * 支持简写生日,比如01,转换为2001,89转换为1989; * 支持任何可以进行时间转换的格式,比如'1989/01/01','1989 01'等 * */ function getShengXiao(birth) { birth += ''; var len = birth.length; if (len < 4 && len != 2) { return false; } if (len == 2) { birth - 0 > 30 ? birth = '19' + birth : birth = '20' + birth; } var year = (new Date(birth)).getFullYear(); var arr = ['猴', '鸡', '狗', '猪', '鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊']; return /^\d{4}$/.test(year) ? arr[year % 12] : false; } /* * * 计算星座 * 支持传递[月日],[月,日],[年月日]等格式,详见例子 * */ function getxingzuo(month, day) { var d = new Date(1999, month - 1, day, 0, 0, 0); var arr = []; arr.push(["魔羯座", new Date(1999, 0, 1, 0, 0, 0)]) arr.push(["水瓶座", new Date(1999, 0, 20, 0, 0, 0)]) arr.push(["双鱼座", new Date(1999, 1, 19, 0, 0, 0)]) arr.push(["牡羊座", new Date(1999, 2, 21, 0, 0, 0)]) arr.push(["金牛座", new Date(1999, 3, 21, 0, 0, 0)]) arr.push(["双子座", new Date(1999, 4, 21, 0, 0, 0)]) arr.push(["巨蟹座", new Date(1999, 5, 22, 0, 0, 0)]) arr.push(["狮子座", new Date(1999, 6, 23, 0, 0, 0)]) arr.push(["处女座", new Date(1999, 7, 23, 0, 0, 0)]) arr.push(["天秤座", new Date(1999, 8, 23, 0, 0, 0)]) arr.push(["天蝎座", new Date(1999, 9, 23, 0, 0, 0)]) arr.push(["射手座", new Date(1999, 10, 22, 0, 0, 0)]) arr.push(["魔羯座", new Date(1999, 11, 22, 0, 0, 0)]) for (var i = arr.length - 1; i >= 0; i--) { if (d >= arr[i][1]) return arr[i][0]; } } return{ shengxiao: getShengXiao, xingzuo: getxingzuo } }() //取文件后缀名 function GetFileExt(filepath) { if (filepath != "") { var pos = "." + filepath.replace(/.+\./, ""); return pos; } } //取文件名不带后缀 function GetFileNameNoExt(filepath) { var pos = strturn(GetFileExt(filepath)); var file = strturn(filepath); var pos1 =strturn( file.replace(pos, "")); var pos2 = GetFileName(pos1); return pos2; } //字符串逆转 function strturn(str) { if (str != "") { var str1 = ""; for (var i = str.length - 1; i >= 0; i--) { str1 += str.charAt(i); } return (str1); } } //取文件全名名称 function GetFileName(filepath) { if (filepath != "") { var names = filepath.split("\\"); return names[names.length - 1]; } }
-
【总结】
最好的方式还是使用动态创建script的方式加载,当动态创建script,浏览器会分配一个线程去下载src指向的资源,多个script也是同步下载的

浙公网安备 33010602011771号