关键词搜索

源码搜索 ×
×

jquery源码学习笔记三:jQuery工厂剖析

发布2017-01-15浏览846次

详情内容

jquery源码学习笔记二:jQuery工厂

jquery源码学习笔记一:总体结构

上两篇说过,query的核心是一个jQuery工厂。其代码如下

function( window, noGlobal ) {

    var jQuery = function( selector, context ) {//首先定义一个内部jQuery。注意,此jQuery只是一个工厂内部的变量,并非我们在外面引用的那个jQuery或$
        return new jQuery.fn.init( selector, context );
    };

    /*然后,对这个内部jQuery对象进行各种增强、扩展*/
    jQuery.fn = jQuery.prototype = {
        //...
    };
    jQuery.extend = jQuery.fn.extend = function() {
        //...
    };
    var init = jQuery.fn.init = function( selector, context, root ) {
        //...
    };
    init.prototype = jQuery.fn;
    jQuery.extend({
        //...
    });
    jQuery.fn.extend({
        //...
    });

    if ( !noGlobal ) {//最后,将内部jQuery赋给了外部,即我们所熟知的那个“$”
        window.jQuery = window.$ = jQuery;
    }

    return jQuery;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

其实目前来讲,最难理解的就是这个:

var jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context );
    };
  • 1
  • 2
  • 3

感觉怎么将孙子赋给了爷爷?究竟是先有鸡还是先有蛋的问题?

其实呢,应该是这么看:

//只是先定义了一个函数而已,还没有执行,无所谓先有鸡还是先有蛋
var jQuery = function( selector, context ) {
        ……
    };
  • 1
  • 2
  • 3
  • 4

好吧,第二点疑惑,为啥要new jQuery.fn.init( selector, context );这么个实例赋给jQuery?

是因为,new给jQuery,这样调用jQuery的时候,就不用再new了,简洁一点。

function( window, noGlobal ) {

    var jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context );
    };

    ……

    if ( !noGlobal ) {
        window.jQuery = window.$ = jQuery;
    }

    return jQuery;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

由上代码可知,jQuery 已经是一个 new 出来的对象。如此,我们在使用jQuery的时候,就没有new这一步了,直接就是$.或者$(““)这样来使用。

往下看,有:

jQuery.fn = jQuery.prototype = {
        //...
    };
  • 1
  • 2
  • 3

为啥这样写呢?有什么玄妙?或者纯粹就是为了装逼?还真是,将原型prototype赋给fn,就是一种简写,不用写成”prototype”这么长。

第四个疑惑:

    jQuery.fn = jQuery.prototype = {
        //...
    };
    jQuery.extend = jQuery.fn.extend = function() {
        //...
    };
    jQuery.extend({
        //...
    });
    jQuery.fn.extend({
        //...
    });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

jQuery.extend和jQuery.fn.extend有啥不一样?

当然不一样了。jQuery.extend扩展(顾名思义)的是实例,而jQuery.fn.extend扩展的是原型。扩展实例,作用仅限于实例;扩展原型,却可以惠及所有实例。扩展原型,可以节省内存。慢着,jQuery不是只有一个实例吗?

不是的,

var jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context );
    };
  • 1
  • 2
  • 3

jQuery随同参数不同,是有许多个实例的。比如,$(“div”) 和 $(“#div1”)是两个不同的实例。

疑惑五:

    var init = jQuery.fn.init = function( selector, context, root ) {
        //...
    };
    init.prototype = jQuery.fn;
  • 1
  • 2
  • 3
  • 4

为什么要把jQuery的原型(jQuery.fn)覆盖它孙子(jQuery.fn.init)的原型?
答曰,因为不这么写的话,jQuery将用不上jQuery.fn,一系列的原型扩展:jQuery.fn.extend()都白费了。为啥呢,因为

var jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context );
    };
  • 1
  • 2
  • 3

意味着当这个函数真正被执行以后,jQuery将被它孙子的实例所替换,所以必须在定义阶段,就要将扩展应用到孙子的原型中。那么,为啥不直接扩展孙子的原型呢,非要扩展爷爷的原型,然后覆盖孙子的原型,再然后构造孙子实例赋给爷爷?真他妈绕啊。搞来搞去,可能就是为了简洁,和显得有点可读性吧?你看,孙子的名字叫做init。

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载