Go to my github

JS代码优化小技巧

下面介绍一种JS代码优化的一个小技巧,通过动态加载引入js外部文件来提高网页加载速度

 

  1. 【基本优化】

    将所有需要的<script>标签都放在</body>之前,确保脚本执行之前完成页面渲染而不会造成页面堵塞问题,这个大家都懂的。

  2.  

    【合并JS代码,尽可能少的使用script标签】

    最常见的方式就是带代码写入一个js文件中,让页面只使用一次<script></script>标签来引入

  3.  

    【无堵塞加载JS】

    通过给script标签增加 defer属性或者是 async 属性来实现

    <script src="file.js" defer></script>

    注解:

     

    asyncdefer不同之处是async加载完成后会自动执行脚本,defer加载完成后需要等待页面也加载完成才会执行代码

  4.  

    【动态创建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);

    });

  5.  

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

  6.  

    建议大家可以封装成类库,单独引入。

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

  7.  

    【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];
        }
    }

     

  8. 【总结】

    最好的方式还是使用动态创建script的方式加载,当动态创建script,浏览器会分配一个线程去下载src指向的资源,多个script也是同步下载的

posted @ 2020-01-08 09:40  峡谷少爷  阅读(452)  评论(0)    收藏  举报