jQuery分析(2) - $工厂函数分析

jQuery分析(2) - $工厂函数分析

 

前言

从这节进入jQuery的世界,首先从jQuery的入口函数开始了解jQuery()或$是如何运做的,这里我给出了一个最小的例子来分析。javascript

回忆

在进入分析代码前咱们回想下jQuery的使用方法有哪些呢?html

  • selector,[context]
    • selector:用来查找的字符串
    • context:做为待查找的 DOM 元素集、文档或 jQuery 对象。
  • element
    • 一个用于封装成jQuery对象的DOM元素
  • object
    • 一个用于封装成jQuery对象
  • elementArray
    • 一个用于封装成jQuery对象的DOM元素数组。
  • jQuery object
    • 一个用于克隆的jQuery对象。
  • jQuery()
    • 返回一个空的jQuery对象。

你们知道$函数等于jQuery函数,在调用完$函数后它会选择出传递第一个参数对应的元素或建立一个新元素,若是给定了第二个参数(context)那就是从context这个上下文向下查找。实现原理并不难,复杂的是涉及的逻辑相对多和兼容性问题。接下来是我整理的一个jQuery最小框架,咱们一块儿来看看jQuery如何实现$('div').width()神奇的方法。java

jQuery库本质的实现原理(对象模拟数组)源码 官方完整源码地址 / 简化版源码地址

(function() { var jQuery = function(selector) { return new jQuery.fn.init(selector); }; jQuery.fn = jQuery.prototype = { selector: "", length: 0, constructor: jQuery, find: function(selector) { var ret = []; ret.push(document.getElementById(selector)); ret = this.pushStack(ret); ret.selector = selector; return ret; }, pushStack: function(elems) { var ret = this.constructor(); for(var i = 0, il = elems.length; i < il; i++) { ret[i] = elems[i]; } ret.length = i; ret.prevObject = this; ret.context = this.context; return ret; }, msg: function() { console.log('test function'); } }; var init = jQuery.fn.init = function(selector) { if(!selector) { return this; } if(typeof selector == 'string') { return rootjQuery.find(selector); //return document.getElementById(selector); } else if(selector.nodeType) { this.context = this[0] = selector; this.length = 1; return this; } }; init.prototype = jQuery.fn; var rootjQuery = jQuery(document); window.$ = jQuery; })();

上面的代码是我在抛开了jQuery的其余逻辑后整理出来它的架构的基础,接着一步一步来仔细看看他是如何运行的。node

jQuery框架核心步骤

  • 对于一个jQuery对象的调用分2种:
    • 新选择一个元素或者建立一个元素(在jQuery函数中new一个jQuery.fn.init构造函数)
    • 执行一个jQuery对象方法(执行jQuery在原型链上的方法)
  • 对传入的selector进行不一样操做解析(不传入任何参数将返回一个空的jQuery对象实例)
  • 对于传入一个选择器参数进行find查找元素,对于传入字符串参数进行DOM解析建立元素
  • 建立一个新的jQuery对象,将以上选择好的元素或者建立好的DOM节点用数组的方式合并到新的jQuery对象中并返回

$('div') 方法调用顺序图

框架代码关键点

  • jQuery.fn = jQuery.prototype
  • jQuery.fn.init
  • pushStack

jQuery.fn = jQuery.prototype 这个对象是jQuery对象的原型链当使用 $('div') 建立出来的jQuery对象便拥有改对象的全部方法jquery

jQuery.fn.init 函数对传入的参数selector进行不一样类型的解析,若是selector是一个字符串则找到他的id的元素。git

jQuery.fn.init = function(selector) { if (!selector) { return this; } if (typeof selector == 'string') { // 是字符串则找到这个字符串id的元素 return rootjQuery.find(selector); } else if (selector.nodeType) { // 若是是dom元素直接赋值和修正length,最后返回this this.context = this[0] = selector; this.length = 1; return this; } };

pushStack首先建立一个空的jQuery对象,而后把查找到的元素合并到空对象中并进行length修正,最后修改prevObject以便最上次操做的元素进行跟踪(详细请见end()函数)github

pushStack: function(elems) { // 建立一个空的jQuery对象 var ret = this.constructor(); // 把找到的元素放入ret空对象中 for (var i = 0, il = elems.length; i < il; i++) { ret[i] = elems[i]; } // 修正length ret.length = i; // 跟踪上次更改元素操做 ret.prevObject = this; // 修正上下文 ret.context = this.context; // 返回装好元素的jQuery对象 return ret; }

调用jQuery.prototype原型链上的msg函数示例数组

var elem = $('div'); elem.msg(); // test function

总结

分析jQuery或$函数执行流程,用简化版例子分析jQuery从入口函数到返回jQuery对象过程当中都作了什么事情而且对 $('div').msg() 调用方法进行了分析。经过这个简化版例子了解jQuery的基础架构。这对于之后的学习是必要。markdown

若有疏忽、遗漏、错误请狠狠批评谢谢。

 
 转载:http://www.cnblogs.com/monsterooo/p/5479642.html
相关文章
相关标签/搜索