zoukankan      html  css  js  c++  java
  • jquery源码解析:expando,holdReady,ready详解

    jQuery的工具方法,其实就是静态方法,源码里面就是通过extend方法,把这些工具方法添加给jQuery构造函数的。

    jQuery.extend({       //当只有一个对象时,就把这个对象中的属性和方法扩展到this对象中,这里的this指向jQuery

      expando: "jQuery" + ( core_version + Math.random() ).replace( /D/g, "" ),      

      //唯一性,core_version 为jQuery的版本号。D的意思是:不是数字的,就选中。因此expando就是jQuery+一段整数。数据缓存,ajax,事件机制都用到了这个。

      noConflict: function( deep ) {    

        //处理冲突,因为有些库可能会用到$甚至jQuery,这时就可以调用chaojidan = $.onConflict(true);这时chaoijdan就可以当做jQuery了,并且其他库可以使用$标识了
        if ( window.$ === jQuery ) {
          window.$ = _$;
        }

        if ( deep && window.jQuery === jQuery ) {
          window.jQuery = _jQuery;
        }

        return jQuery;
      }, 

      isReady: false,

      readyWait: 1,

      holdReady: function( hold ) {
        if ( hold ) {
          jQuery.readyWait++;
        } else {
          jQuery.ready( true );
        }
      },

      ready: function( wait ) {

        if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
          return;
        }

        jQuery.isReady = true;

        if ( wait !== true && --jQuery.readyWait > 0 ) {
          return;
        }

        readyList.resolveWith( document, [ jQuery ] );

        if ( jQuery.fn.trigger ) {
          jQuery( document ).trigger("ready").off("ready");
        }
      },

      //以上几个属性和方法其实就是解决DOM加载问题的,大家都知道onload是等DOM树建造完成,并且资源加载完成才会触发。但是我们只需要DOM树构造完成,就执行绑定事件,所以有一个DOMContentLoaded事件。但是低版本浏览器不支持,所以需要兼容,jQuery就写了兼容方法。所以在这里介绍一下它是怎么处理的。

      $(function(){}) -> $(document).ready(function(){}) -> $().ready() -> jQuery.ready.promise().done(fn),

        jQuery.ready.promise = function( obj ) {
          if ( !readyList ) {       //第一次调用时,为空,所以进入。之后就直接使用这个对象

            readyList = jQuery.Deferred();     //新建一个延迟对象

            if ( document.readyState === "complete" ) {  

              //DOM已经加载结束了,这时就可以直接调用jQuery.ready,不用再绑定事件了
              setTimeout( jQuery.ready );  

              //DOM快加载好的时候,IE的readyState有可能就是complete了,这时调用jQuery.ready会出问题,因此延迟调用,确保IE下也没问题。

            } else {

              document.addEventListener( "DOMContentLoaded", completed, false );

              window.addEventListener( "load", completed, false );

              //火狐浏览器可能会缓存onload事件,这时onload会先于DOMContentLoaded触发。写两个,更保险
            }
          }
          return readyList.promise( obj );  //延迟对象的状态有几种,在外面可以被修改,但是promise不能修改
        };   

        completed = function() {
          document.removeEventListener( "DOMContentLoaded", completed, false );   //只调用一次completed 方法
          window.removeEventListener( "load", completed, false );
          jQuery.ready();
        };

        //jQuery.ready.promise().done(fn)  (延迟对象调用done方法,把fn方法加入延迟对象,当触发延迟对象的resolveWith时,就会执行fn方法) -> jQuery.ready() -> readyList.resolveWith( document, [ jQuery ] )   

        ready: function( wait ) {

          if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {   
            return;
          }

          jQuery.isReady = true;   //只触发一次

          if ( wait !== true && --jQuery.readyWait > 0 ) {   //DOM的ready正常触发时,也要检查是否需要等待
            return;
          }

          readyList.resolveWith( document, [ jQuery ] );

          //第一个参数是指向this(回调方法的执行上下文),第二个参数是传给回调方法的参数。这个回调方法,就是通过延迟对象的done方法加进来的fn.因此,resolveWith( document, [ jQuery ] );相当于fn(jQuery),在document中执行。

          if ( jQuery.fn.trigger ) {   //这里处理jQuery第三种DOM加载完成执行js的方式。
            jQuery( document ).trigger("ready").off("ready");   //触发ready事件后,马上移除掉,只触发一次。

            //$(document).on("ready",function(){}),通过document绑定ready事件来实现。
          }
        },

        holdReady: function( hold ) {   //阻止Dom加载完成执行function,$.holdReady(true),
          if ( hold ) {
            jQuery.readyWait++;   //要加载多个文件时(a.js,b.js),就要每次都++。
          } else {
            jQuery.ready( true );    //$.holdReady(false),恢复执行,减少一次jQuery.readyWait,直到它为0.
          }
        },

        这个方法有什么用呢?举个例子:$.getScript("a.js",function(){});  $(function(){ a.say(); });这个代码的意思是加载完a.js,然后再调用a的say 方法。但是a.js需要下载,所以执行a.say会报错。这时,可以先$.holdReady(true),这样$(function(){ a.say(); }中的a.say(); 就不会执行了。直到我在$.getScript("a.js",function(){$.holdReady(false)});才可以执行。而这时,a.js加载完成,并执行结束后,调用回调方法,执行$.holdReady(false),恢复执行。

      

      

      isFunction: function( obj ) {     //在低版本IE浏览器下typeof alert   返回object,而不是function
        return jQuery.type(obj) === "function";
      },

      isArray: Array.isArray,   //不兼容IE8以及以下版本

      isWindow: function( obj ) {
        return obj != null && obj === obj.window;  

        //false == null  ->  false ,true == null -> false。只有null和undefined才等于null,而只有这两个变量没有属性。其他的像字符串有包装对象,可以有属性。window有两种意思:(1)全局对象,(2)浏览器窗口。而只有window才有window属性,因此只有window才会返回true.window.window表示全局对象中的浏览器窗口。
      },

      isNumeric: function( obj ) {   //typeof NaN   ->  number
        return !isNaN( parseFloat(obj) ) && isFinite( obj );    //Number.MAX_VALUE最大值,加1就会是无限大,就不是number类型

        //先判断参数是否能转成数字,不可以就是NaN,那么isNaN就会返回true。如果是数字,但是必须是有限数,不然也不是number类型。
      },

      ...

    })

    加油!

  • 相关阅读:
    Mina、Netty、Twisted一起学习(三):TCP前缀固定大小的消息(Header)
    集装箱set相关算法
    企业视觉-大型电商(制)-高性能的用户视觉性能(1)
    周期节
    在近排博客活动已被删除几篇文章
    [Python] Different ways to test multiple flags at once in Python
    [Angular] Use :host-context and the ::ng-deep selector to apply context-based styling
    [Javascirpt AST] Babel Plugin -- create new CallExpression
    [Python] Object spread operator in Python
    [Javascript AST] 3. Continue: Write ESLint rule
  • 原文地址:https://www.cnblogs.com/chaojidan/p/4152029.html
Copyright © 2011-2022 走看看