【jQuery源码浅析】(二)--jQuery的构造--$()

来源:互联网 发布:淘宝双11是什么意思 编辑:程序博客网 时间:2024/05/17 13:14

前言

很多人在使用jQuery的时候可能会问,jQuery是什么,是一个,还是一个对象?如果 $() instanceof jQuery === true ,那么jQuery是一个类(js中没有类的概念,准确来说$()jQuery的实例)。如果是这样的话,那么new jQuery()出来的什么呢?因此就要从源码入手,分析jQuery到底是个什么东西。

如果从源码直接入手会非常地迷茫,很难弄懂作者想表达的是什么思想。但是如果从更高的维度去看问题,直接了解作者的目的,也就是从api入手,那我们看源码时候就会有更好的理解。

核心源码

    // jQuery初始化        "use strict";94      var jQuery = function( selector, context ) {            return new jQuery.fn.init( selector, context );99      };114     jQuery.fn = jQuery.prototype = {119         constructor: jQuery            ....193     };2959    init = jQuery.fn.init = function( selector, context, root ) {            ....3056    };3059    init.prototype = jQuery.fn;

思路分析

  1. 用法: jQuery的用法,$(selector,[context]).do1().do2()$.do()
  2. 通用: 不想让开发者写一个new而在内部把jQuery new出来
  3. 目标: new一个jQuery出来后的实例可以访问jQuery的所有对象方法

有了这个思路后,就可以从源码入手解读jQuery是如何构造出来的了☟☟☟

源码分析

1) jQuery构造器内部返回的是一个对象,所以jQuery()和new jQuery()是一样的,那么到底jQuery.fn是一个什么东西呢?我们接着看下去

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

2) 原来jQuery.fn就是jQuery.prototype,也就是说,new出来的jQuery是jQuery原型里面的一个叫做init的东西

        jQuery.fn = jQuery.prototype = {            constructor: jQuery            ....        };

3) 然后仔细看这个重写的jQuery.prototype里面的constructor

        constructor: jQuery

为什么要重新指定其constructor呢?原因如下

相当于 jQuery.prototype.constructor = jQuery
由于采用对象字面量的方式jQuery.prototype = {} 重写了 jQuery.prototype

如果不加上下面这句,jQuery.prototype.constructor 将指向 Object, 为了严谨,可以在使用jQuery.prototype = {} 重写整个 jQuery.prototype 的时候 加上此句,手动让jQuery.prototype.constructor 指回 jQuery

如果采用 jQuery.prototype.init = function(){} 的方法一个一个新增原型方法 则不需要添加下面这句,jQuery.prototype.constructor默认指向 jQuery

也就是说,作者想在所有的实例对象里面调用jQuery(),是真正的调用jQuery,而不是实例一个Object。其实不加这句话也没有什么大问题,只是在调用jQuery.prototype.constructor()时候起到关键作用。

4)那么再看一下下一步的init要干什么。咋一看,init内部实现的到底是什么呢,其实我暂时不关心这里,因为内部的操作基本上是return this或者return jQuery.makeArray( selector, this )。内部用递归实现了一个叫jQuery.prototype.init的东西。那么到底init内部是怎样实现的呢,我往后再谈。

        init = jQuery.fn.init = function( selector, context, root ) {            if ( !selector ) {                return this;            }            if ( match && ( match[ 1 ] || !context ) ) {                if ( match[ 1 ] ) {}                else {                    return this;                }            }            else if ( !context || context.jquery ) {                return ( context || root ).find( selector );            } else {                return this.constructor( context ).find( selector );            }            return jQuery.makeArray( selector, this );        };

5) 最后一步很关键,我已经把jQuery.prototype.init new出来了,那么我应该怎么去操纵jQuery.prototype里面所有的方法呢?

        init.prototype = jQuery.fn;

答案就是就把init.prototype设置成jQuery.prototype,这样我所有new出来的init的原型都是jQuery.prototype了,就可以操纵jQuery的原型的所有方法了。如果不加这句话,就会出现Uncaught TypeError: jQuery(...).find is not a function的错误了。

最后总结

最后,如果有人问你,jQuery到底是个什么东西啊,你就可以说jQuery其实不是个什么东西,它只是一个构造器,真正创造的是一个叫做jQuery.prototype.init的东西,这个init是一个更加抽象的东西,是经过反复递归而创造出来的一个“鬼东西”,我们将这个init理解为jQuery。

相关资料

  • 【深入浅出jQuery】源码浅析–整体架构
  • jQuery3.1.1.js源码下载
原创粉丝点击