jQuery源码学习(一) 整体架构

本文针对的是jQuery 1.11.1版本,学习jQuery的源码是为了能够领略大师的编程思想,和考虑问题的方式,以后争取每天更新。

(function( global, factory ) {

    if ( typeof module === "object" && typeof module.exports === "object" ) {
        // For CommonJS and CommonJS-like environments where a proper window is present,
        // execute the factory and get jQuery
        // For environments that do not inherently posses a window with a document
        // (such as Node.js), expose a jQuery-making factory as module.exports
        // This accentuates the need for the creation of a real window
        // e.g. var jQuery = require("jquery")(window);
        // See ticket #14549 for more info
        module.exports = global.document ?
            factory( global, true ) :
            function( w ) {
                if ( !w.document ) {
                    throw new Error( "jQuery requires a window with a document" );
                }
                return factory( w );
            };
    } else {
        factory( global );
    }

// Pass this if window is not defined yet
}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
}));

首先看代码的整体架构,jQuery通过IIFE的方式,对commonJS,AMD和其他的调用方式做了一个兼容。
我们可以看到因为使用的是()();的IIFE的方式,所以函数会在声明后立即被调用,而被调用的函数的两个参数:
全局变量global对应typeof window !== "undefined" ? window : this,
工厂函数factory对应function( window, noGlobal ) {}
在global上做了一次判断,如果window存在,则全局变量定义在window下,如果window不存在,则把全局变量定义在当前上下文(this)里,这主要是为了兼容如nodeJS这样没有window对象的环境。
再看被调用函数的函数体:
首先是判断module和module.exports是否为对象,如果是对象的话,可以认为目前是处在commonJS或者类commonJS的环境里(比如nodeJS环境里)。
这时再判断全局变量是否有document对象,浏览器环境下是有window.document的,而nodeJS环境下则没有,如果有document对象,则把global传进factory中来构造jQuery,否则的话就抛出一个“jQuery requires a window with a document”错误,毕竟jQuery的主要使命是简化DOM操作,如果没有document的话就没有存在的意义。

如果判断目前不是处在类commonJS环境中,即不是在nodeJS环境中时,我们就可以大胆的使用factory来构造jQuery了。

总结:

jQuery的构造离不开document对象,而commonJS环境中恰好存在没有document的上下文的情况,因此需要对这种情况做一个规避。