jQuery分析(2) - $工厂函数分析
前言
从这节进入jQuery的世界,首先从jQuery的入口函数开始了解jQuery()或$是如何运作的,这里我给出了一个最小的例子来分析。
回忆
在进入分析代码前我们回想下jQuery的使用方法有哪些呢?
- 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()神奇的方法。
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的其他逻辑后整理出来它的架构的基础,接着一步一步来仔细看看他是如何运行的。
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.fn.init 函数对传入的参数selector进行不同类型的解析,如果selector是一个字符串则找到他的id的元素。
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()函数)
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的基础架构。这对于以后的学习是必要。
如有疏忽、遗漏、错误请狠狠批评谢谢。
jQuery分析(2) - $工厂函数分析的更多相关文章
- jQuery基础的工厂函数以及定时器的经典案例
1. jQuery的基本信息: 1.1 定义: jQuery是JavaScript的程序库之一,它是JavaScript对象和实用函数的封装, 1.2 作用: 许多使用JavaScript能实现的交 ...
- jQuery1.11源码分析(4)-----Sizzle工厂函数[原创]
在用前两篇讲述完正则表达式.初始化.特性检测之后,终于到了我们的正餐——Sizzle工厂函数! Sizzle工厂函数有四个参数, selector:选择符 context:查找上下文 results: ...
- jQuery源码解读-事件分析
最原始的事件注册 addEventListener方法大家应该都很熟悉,它是Html元素注册事件最原始的方法.先看下addEventListener方法签名: element.addEventList ...
- JQuery data API实现代码分析
JQuery data 接口是什么? .data() Store arbitrary data associated with the matched elements or return the v ...
- jQuery 源码分析 8: 回头看jQuery的构造器(jQuery.fn,jQury.prototype,jQuery.fn.init.prototype的分析)
在第一篇jQuery源码分析中,简单分析了jQuery对象的构造过程,里面提到了jQuery.fn.jQuery.prototype.jQuery.fn.init.prototype的关系. 从代码中 ...
- jQuery学习笔记之jQuery.fn.init()的参数分析
这篇文章主要介绍了jQuery.fn.init()的参数分析,需要的朋友可以参考下 从return new jQuery.fn.init( selector, context, rootjQuer ...
- [js]jQuery EasyUI的linkbutton组件disable方法无法禁用jQuery绑定事件的问题分析
问题由来 linkbutton 是 jQuery EasyUI 中常用的一个控件,可以使用它创建按钮.用法很简单,使用 a 标签给一个easyui-linkbutton 的class就可以了. < ...
- jQuery基础,定时器,工厂函数
这个星期刚刚学的JQuery,下面我来说说我学的这几个例子 jQuery是JavaScript的一个程序库. Jquery的工厂函数$(): 在Jquery中 $符号等价于jquery,作用是将DOM ...
- split(),preg_split()与explode()函数分析与介
split(),preg_split()与explode()函数分析与介 发布时间:2013-06-01 18:32:45 来源:尔玉毕业设计 评论:0 点击:965 split()函数可以实 ...
随机推荐
- leetcode 二分查找
https://oj.leetcode.com/problems/search-for-a-range/就是一个二分查找,没事练练手 public class Solution { public in ...
- 洛谷P1407 工资
洛谷P1407 工资 本题地址:http://www.luogu.org/problem/show?pid=1407 题目描述 有一家世界级大企业,他们经过调查,发现了一个奇特的现象,竟然在自己的公司 ...
- [ZETCODE]wxWidgets教程六:事件处理
本教程原文链接:http://zetcode.com/gui/wxwidgets/events/ 翻译:瓶哥 日期:2013年12月7号星期六 邮箱:414236069@qq.com 主页:http: ...
- C++类实现AVL树
二叉查找树是个好东西,他让查找,插入,删除,这些常用操作变得高效,但是,他是存在问题的,那就是,在坏的输入序列下,树会退化成链表,这就很尴尬了,于是为了避免这种情况的发生,我们需要一种数据结构,可以自 ...
- Java--创建线程及常用方法
继承java.lang.Thread类--Thread类代表线程类 它的常用方法如下: static Thread currentThread():返回当前正在运行的线程对象的引用. static ...
- Nginx+tomcat负载均衡并动静态分离
Nginx使用正则表达式配置location,指定某些后缀的文件直接从文件路径中找(如*.jpg直接去C:/XX/XX/XX/img下找),其他的请求转发给tomcat 同时可以配置多个tomcat ...
- HttpClient中post请求http、https示例
HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建 ...
- linux安装apache软件的过程
参考官方安装指导:http://httpd.apache.org/docs/2.4/install.html 1.下载依赖包 apr/apr-util/pcre 2.解压依赖包 3.安装apr 进入安 ...
- hibernate sql查询
如果你跟我一样比较熟悉SQL,同时不想学习一门新的语言.那么在hibernate中使用Native SQL 查询也是一种不错的方式. 一方面,Native SQL在效率方面有天生的优势: 另一方面,S ...
- Zend Framework 2参考Zend\Authentication(Zend\Authentication介绍)
原文:Zend Framework 2参考Zend\Authentication(Zend\Authentication介绍) Zend\Authentication组件提供了认证接口和具体的通用的认 ...