jQuery源码阅读-jQuery是如何定义的

homeros    前端    999+ 次    2017-12-12 17:29:36


如果我们要重头设计一个jQuery,用户要创建一个jQuery对象,怎么创建?

最直接的方法:

// 执行匿名函数
(function() {
    var jQuery = function(selector) {
        this.selector = selector;
    }
  
    window.jQuery = jQuery;
})();
// 创建jQueyr对象
var obj = new jQuery("div");

但很讨厌,每次都要写一个new关键字,但如何避免每次都要写一个new呢?

很自然的,下面是一种解决方法:

(function() {
    var jQuery, init;
    init = function(selector) {
        this.selector= selector;
    }
 
    jQuery = function(selector) {
        return new init(selector);
    }
 
    window.jQuery = jQuery;
    // 除了向外暴露jQuery全局变量外,还需要暴露init全局变量,否则无法扩展jQuery对象
    window.init = init;
})();
// ========测试代码=============
var b = jQuery("div");
console.log(b);
// 当需要扩展jQuery对象时,需要修改init的prototype。
// jQuery.prototype.attr = function() { alert("implementation of attr function"); }  
// 上述是错误的写法,修改jQuery的prototype并不会扩展new init()创建的对象
init.prototype.attr = function() { alert("implementation of attr function"); };
b.attr();

以上的代码是没有什么大问题的,但如果这样的话,当用户需要扩展jQuery对象的方法时(即jQuery插件),显然的是要暴露两个全局变量jQuery和init,否则用户无法扩展jQuery对象。

那么怎么做才能尽可能少的暴露全局变量呢?我们可以把jQuery的prototype指向init的prototype,这样,当扩展jQuery的prototype时,也意味着修改了init的prototype


(function() {
    var jQuery, init;
    init = function(selector) {
        this.selector= selector;
    }
 
    jQuery = function(selector) {
        return new init(selector);
    }
 
    // 把init的prototype指向jQuery的prototype,这样,当扩展jQuery的prototype时,也意味着修改了init的prototype
    jQuery.prototype = init.prototype;
 
    window.jQuery = jQuery;
})();
// ========测试代码=============
var b = jQuery("div");
console.log(b);
 
// 当需要扩展jQuery对象时,只需修改jQuery的prototype。
jQuery.prototype.attr = function() { alert("implementation of attr function"); };
b.attr();

上面的思路也大致是jQuery的设计思路,但jQuery更进一步,它认为init是jQuery对象的构造函数,也应该可以通过jQuery对象访问,因此jQuery里直接将init定义为jQuery.prototype中的一个成员。

jQuery中定义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 have a `window` with a `document`
        // (such as Node.js), expose a 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 ) {
 
 
var
    version = "1.12.4",
 
 
    // Define a local copy of jQuery
    // 重点代码
    jQuery = function( selector, context ) {
        // The jQuery object is actually just the init constructor 'enhanced'
        // Need init if jQuery is called (just allow error to be thrown if not included)
        return new jQuery.fn.init( selector, context );
    };
 
// 重点代码
jQuery.fn = jQuery.prototype = {
};
 
// A central reference to the root jQuery(document)
var rootjQuery,
 
    // 重点代码
    init = jQuery.fn.init = function( selector, context, root ) {
         
    };
// Give the init function the jQuery prototype for later instantiation
// 重点代码
init.prototype = jQuery.fn;
 
// Expose jQuery and $ identifiers, even in
// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if ( !noGlobal ) {
    window.jQuery = window.$ = jQuery;
}
 
return jQuery;
}));

上一篇: javascript中的类型转换

下一篇: ansible 01

最新评论

暂无评论

热门文章

最新评论

网站数据

网站文章数:481

今日UV/PV/IP:26/30/26

昨日UV/PV/IP:23/30 /23

TOP