jQuery对象是使用构造函数和原型模式相结合的方式创建的。现在来看看jQuery的原型对象jQuery.prototype:

 jQuery.fn = jQuery.prototype = {
//成员变量和方法
}

这里给原型对象起了一个别名叫做jQuery.fn。要注意的是这个jQuery.fn可不是jQuery对象的属性,而是jQuery构造方法本身的属性,它是不会传给它所创建的对象的。如果你在控制台敲$().fn的话输出的结果会是undefined。接下来看看原型对象里面有些什么:

 jquery: "2.1.1",

 constructor: jQuery,

jquery:在原型对象中,先定义了jquery属性来标识版本信息,这里是2.1.1版。在我们写代码的时候可以通过查看这个属性判断对象是不是jQuery对象。

constructor:这个属性在低版本的jQuery代码中是没有的(例如远古的1.2.6版本)。在这里我能看见这个属性我真的觉得现在的jQuery成熟了。每一个对象都有一个constructor属性,是由创建它的构造函数的原型对象传递而来,指向了创建它的构造方法。也就是如果你在chrome的控制台敲:

 var obj = {};

 obj.constructor;

控制台会显示:

  function Object() { [native code] }

构造函数的原型是在定义构造函数的时候自动生成,其中的constructor会自动指向该构造函数。也就是你在输入:

 function Obj(){}

 Obj.prototype.constructor

控制台会输出:

  function Obj(){}

现在回过头我们再来看看jQuery的代码。定义jQuery.prototype时:

 jQuery.fn = jQuery.prototype = {
//成员变量和方法
}

这里的过程其实是新建一个对象,然后将jQuery.prototype指向这个新建的对象。而这时新建对象因为是由function Object(){}方法构建的。所以它的constructor属性其实是指向的function Object(){}方法。进而导致所有由jQuery方法创建的对象的constructor也是指向的

function Object(){}方法。这里重新定义jQuery.prototype.constructor属性,让它重新指向jQuery构造函数。平常我们在使用jQuery的时候也许永远也不会用到constructor这个属性,但是这种小细节的完善无疑让整个代码变得严谨很多。

继续往下看代码:

 // Start with an empty selector
selector: "", // The default length of a jQuery object is 0
length: 0,

selector:这个属性指的是默认的选择器。

length:jQuery对象其实是一个类数组对象。什么叫类数组对象?我的理解是它不是一个数组,而是一个对象但是当我们访问它的数据时某些表现形式跟数组很相似,比如可以用[0]、[1]....[n]来访问数据,可以用length来获取数据的数目。jQuery就是一种类数组对象通过选择器选择页面dom元素,并以jq[0]、jq[1]、jq[2]...、jq[n]的形式将个元素存储在jQuery对象中,这个length属性就是用来记录元素个数。

继续往下:

 var arr = [];

 var slice = arr.slice;

 toArray: function() {
return slice.call(this);
},

toArray:这个方法是将jQuery对象转化为一个数组(是真正的数组哦)。我们知道数组的

slice(start,end)

方法可从已有的数组中返回选定的元素而不破坏原有的数组,当参数不填的时候就返回这个数组的一个副本。因为jQuery对象是类数组对象,所以这里直接将数组arr中slice的对象上下文换成当前jQuery对象(不知道这个对象上下文能不能理解成作用域哈,不过this肯定是指的新对象啦)。slice函数执行后返回一个真正的js数组,里面的元素就是jQuery对象中的各个dom元素,但是又不破坏原来的jQuery对象,这一招真的挺不错,一行代码使用现有的资源解决了很多事情,这种思路要多学习。不过slice的调用我们还可以用

Array.prototype.slice.call(this)

这种方式调用也是可以的,不用特意新建一个对象。

往下:

 get: function(num) {
return num != null ? // Return just the one element from the set
(num < 0 ? this[num + this.length] : this[num]) : // Return all the elements in a clean array
slice.call(this);
},

get:这个方法感觉根据传参不同会有两个功能。一个是如果传参num不为空的话,那么根据num返回jQuery对象中的相应dom元素。另一个就是当num为空得时候将jQuery对象转换为数组。所以我一直很奇怪为啥有了get方法还要专门写一个toArray方法,希望有大大为我解惑。

咱们继续:

 pushStack: function(elems) {

     // Build a new jQuery matched element set
//jQuery.merge:合并两个数组的内容到第一个数组中
var ret = jQuery.merge(this.constructor(), elems); // Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context; // Return the newly-formed element set
return ret;
},

pushStack:大家都知道当我们使用jQuery选择区创建jQuery对象后,例如$(".class"),还可以使用jq.find、jq.filter等方法进一步处理,返回新的jQuery对象。但是这样往往会对旧的jQuery产生“破坏”性德影响,因为它们会修改匹配元素的集合(在jQuery中被称为matched element set)所以jQuery在进行这种“破坏性”的操作之前就会调用pushStack方法将现有的匹配元素集合暂时保存起来。

首先调用jQuery.merge方法,它将两个数组合并到第一个数组中。不过我觉得很有意思的是两个传参:

第一个参数this.constructor指的是jQuery构造方法原型对象中的constructor属性,这个前面说过。的this.constructor()指的是调用jQuery构造方法构建一个新对象,如同$()一样。因为jQuery是类数组对象所以也可以充当merge的传参。我觉得很炫酷的是这里创建新jQuery的写法,要是我本人的话我肯定会直接用jQuery()这么写了。

第二个参数elems就是pushStack传进来的参数了,它可以是真正的数组,也可以是类数组对象。通过merge方法,可以将elems转化为一个jQuery对象。

接下来就很简单了,将当前对象用ret.prevObject保存起来,值得一提的是这里还专门用了一个ret.context来保存当前jQuery对象的选择器上下文,就是使用选择器匹配元素时第二个参数,eg:$("div",document.getElementById("id"))。我查了一下w3c.school,context 属性在 jQuery version 1.10 中被弃用,但是高版本的jQuery中还能看到这个,所以我也不知道到底怎么回事。

不过既然说到jQuery.merge了那干脆来看看它吧:

 merge: function(first, second) {
var len = +second.length,
j = 0,
i = first.length; for (; j < len; j++) {
first[i++] = second[j];
} first.length = i; return first;
},

具体代码就不细说了~~~没什么技术含量,值得一提的是从merge的代码上看好像并没有去重的功能。这里的去重不仅仅是重复数字什么的,更包含重复的元素。比方说:

 var arr1 = [], arr2 = [];

 var ele = document.getElementById("id");

 arr1.push(ele);
arr2.push(ele); var arr3 = jQuery.merge(arr1, arr2);

运行后arr3.length将会是2虽然两个元素其实是同一个dom对象的引用。

菜鸟的jQuery源码学习笔记(二)的更多相关文章

  1. 菜鸟的jQuery源码学习笔记(前言)

    前言 相信任何一名前端开发人员或者是前端爱好者都对jQuery不陌生.jQuery简单易用,功能强大,特别是拥有良好的浏览器兼容性,大大降低了前端开发的难度,使得前端开发变得“平易近人起来”.自从本人 ...

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

    笔记一里记录,jQuery的总体结构如下: (function( global, factory ) { //调用factory(工厂)生成jQuery实例 factory( global ); }( ...

  3. jQuery源码学习笔记二

    //添加实例属性和方法 jQuery.fn = jQuery.prototype = { // 版本,使用方式:$().jquery弹出当前引入的jquery的版本 jquery: core_vers ...

  4. 菜鸟的jQuery源码学习笔记(一)

    整个jQuery是一个自调用的匿名函数: (function(global, factory) { if (typeof module === "object" && ...

  5. 菜鸟的jQuery源码学习笔记(三)

    each: function(callback, args) { return jQuery.each(this, callback, args); }, each:这个调用了jQuery.each方 ...

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

    jquery源码学习笔记二:jQuery工厂 jquery源码学习笔记一:总体结构 上两篇说过,query的核心是一个jQuery工厂.其代码如下 function( window, noGlobal ...

  7. jQuery源码学习笔记一

    学习jQuery源码,我主要是通过妙味视频上学习的.这里将所有的源码分析,还有一些自己弄懂过程中的方法及示例整理出来,供大家参考. 我用的jquery v2.0.3版本. var rootjQuery ...

  8. jquery源码学习笔记(一)jQuery的无new构建

    本人是一名.net程序员..... 你一个.net coder 看什么jQuery 源码啊? 原因吗,很简单.技多不压身吗(麻蛋,前端工作好高...羡慕). 我一直都很喜欢JavaScript,废话不 ...

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

    练武不练功,到老一场空.计算机也一样. 计算机的功,就是原理.如果程序员只会使用各种函数,各种框架,而不知其原理,顶多熟练工人而已.知其然,更要知其所以然. jquery我们用得很爽,但它究竟咋实现的 ...

随机推荐

  1. [C++程序设计]返回指针值的函数

    定义指针函数的一般形式为 类型名 *函数名(参数表列); 例如 int *a(int x,int y);

  2. jquery.fn.extend与jquery.extend(转)

    jQuery为开发插件提拱了两个方法,分别是: JavaScript代码 jQuery.fn.extend(object); jQuery.extend(object); jQuery.extend( ...

  3. 垃圾回收GC——JVM之七

    垃圾回收是个复杂的过程: 请以此阅读下列文章: 垃圾回收1:http://blog.csdn.net/sun305355024sun/article/details/41394729 垃圾回收2:ht ...

  4. Java iText5.5.1 绘制PDF表格

    iText下载链接:http://sourceforge.net/projects/itext/files/ 会有两个文件夹:extrajars中的extrajars-2.3.jar文件用于解决中文不 ...

  5. USB设备类型代码(class类型)

    Base Class E0h (Wireless Controller) This base class is defined for devices that are Wireless contro ...

  6. Asp.net 处理程序(第五篇)

    HttpApplication有19个标准事件,当到达第8个事件PostMapRequestHandler触发的时候,标志着已经获取到了处理请求的处理程序对象,在第11个事件PreRequestHan ...

  7. java设计模式--创建模式--工厂方法

    工厂方法定义: 工厂方法 概述 定义一个用于创建对象的接口,让子类决定实例化哪一个类.FactoryMethod使一个类的实例化延迟到其子类. 适用性 .当一个类不知道它所必须创建的对象的类的时候. ...

  8. bzoj1641 [Usaco2007 Nov]Cow Hurdles 奶牛跨栏

    Description Farmer John 想让她的奶牛准备郡级跳跃比赛,贝茜和她的伙伴们正在练习跨栏.她们很累,所以她们想消耗最少的能量来跨栏. 显然,对于一头奶牛跳过几个矮栏是很容易的,但是高 ...

  9. Volist标签 key值的使用

    Volist标签是thinkphp框架view中常用到的一个标签.主要用于在模板中循环输出数据集或者多维数组.今天使用key属性时出了点问题,记录一下. volist标签(循环输出数据) 闭合 非闭合 ...

  10. java中的TreeMap如何顺序按照插入顺序排序

    java中的TreeMap如何顺序按照插入顺序排序 你可以使用LinkedHashMap  这个是可以记住插入顺序的. 用LinkedHashMap吧.它内部有一个链表,保持插入的顺序.迭代的时候,也 ...