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++ 迭代器

    原地址:http://www.cnblogs.com/marchtea/archive/2012/02/27/2370068.html 前言: 以下的内容为我阅读c++沉思录18,19,20章的笔记以 ...

  2. UVA11806Cheerleaders(容斥)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 题目意思:在m行n列的矩形网格中放k个相同的石子,问有多少中方法?每个格子最多放一 ...

  3. C++程序中不同变量、函数在内存中内存中的分布情况

    一.一个C++编译的程序占用的内存分为以下几个部分 1.栈区:由编译器自动分配 存放函数的参数值,局部变量的值等,操作方式类似于数据结构中的栈. 2.堆区:一般由程序员分配释放,若程序员不释放,程序结 ...

  4. android listview Caused by: java.lang.ArrayIndexOutOfBoundsException: length=3; index=3

    android listview 适配器在多种类型viewType报错: Caused by: java.lang.ArrayIndexOutOfBoundsException: length=3; ...

  5. ccf练习---节日

    问题描述 有一类节日的日期并不是固定的,而是以“a月的第b个星期c”的形式定下来的,比如说母亲节就定为每年的五月的第二个星期日. 现在,给你a,b,c和y1, y2(1850 ≤ y1, y2 ≤ 2 ...

  6. 利用7z实现一键解压

    目的: 实现双击zip,7z,rar等文件时自动解压,解压完毕后自动打开文件夹. 工具: [本文末尾附有所有工具的下载地址] 7z.exe types 步骤: 新建"7z-自动解压" ...

  7. PHP中output control

    Output Control 函数可以让你自由控制脚本中数据的输出.它非常地有用,特别是对于:当你想在数据已经输出后,再输出文件头的情况.输出控制函数不对使用 header() 或 setcookie ...

  8. js Array数组的使用

    js Array数组的使用   Array是javascript中的一个事先定义好的对象(也可以称作一个类),可以直接使用 创建Array对象 var array=new Array(): 创建指定元 ...

  9. Linux系统编程(23)——信号的阻塞

    实际执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending).进程可以选择阻塞(Block)某个信号.被阻塞的信号产生时将保持在未决状态,直到进程 ...

  10. C语言的本质(36)——makefile基础

    除了Hello World这种极简单的程序之外,一般的程序都是由多个源文件编译链接而成的,这些源文件的处理步骤通常用Makefile来管理.makefile带来的好处就是--"自动化编译&q ...