jQuery源码分析-03构造jQuery对象-源码结构和核心函数


Posted in Javascript onNovember 14, 2011

作者:nuysoft/高云 QQ:47214707 EMail:nuysoft@gmail.com
毕竟是边读边写,不对的地方请告诉我,多多交流共同进步。本章还未写完,完了会提交PDF。
前记:
想系统的好好写写,但是会先从感兴趣的部分开始。
近期有读者把PDF传到了百度文库上,首先感谢转载和传播,但是据为已有并设置了挺高的财富值才能下载就不好了,以后我整理好了会传到文库上。请体谅一下。
3. 构造jQuery对象
3.1 源码结构
先看看总体结构,再做分解:

(function( window, undefined ) { 
var jQuery = (function() { 
// 构建jQuery对象 
var jQuery = function( selector, context ) { 
return new jQuery.fn.init( selector, context, rootjQuery ); 
} 
// jQuery对象原型 
jQuery.fn = jQuery.prototype = { 
constructor: jQuery, 
init: function( selector, context, rootjQuery ) { 
// selector有以下7种分支情况: 
// DOM元素 
// body(优化) 
// 字符串:HTML标签、HTML字符串、#id、选择器表达式 
// 函数(作为ready回调函数) 
// 最后返回伪数组 
} 
}; 
// Give the init function the jQuery prototype for later instantiation 
jQuery.fn.init.prototype = jQuery.fn; 
// 合并内容到第一个参数中,后续大部分功能都通过该函数扩展 
// 通过jQuery.fn.extend扩展的函数,大部分都会调用通过jQuery.extend扩展的同名函数 
jQuery.extend = jQuery.fn.extend = function() {}; 
// 在jQuery上扩展静态方法 
jQuery.extend({ 
// ready bindReady 
// isPlainObject isEmptyObject 
// parseJSON parseXML 
// globalEval 
// each makeArray inArray merge grep map 
// proxy 
// access 
// uaMatch 
// sub 
// browser 
}); 
// 到这里,jQuery对象构造完成,后边的代码都是对jQuery或jQuery对象的扩展 
return jQuery; 
})(); 
window.jQuery = window.$ = jQuery; 
})(window);

l jQuery对象不是通过 new jQuery 创建的,而是通过 new jQuery.fn.init 创建的
var jQuery = function( selector, context ) { 
return new jQuery.fn.init( selector, context, rootjQuery ); 
}

n jQuery对象就是jQuery.fn.init对象
n 如果执行new jQeury(),生成的jQuery对象会被抛弃,最后返回 jQuery.fn.init对象;因此可以直接调用jQuery( selector, context ),没有必要使用new关键字
l 先执行 jQuery.fn = jQuery.prototype,再执行 jQuery.fn.init.prototype = jQuery.fn,合并后的代码如下:
jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
所有挂载到jQuery.fn的方法,相当于挂载到了jQuery.prototype,即挂载到了jQuery 函数上(一开始的 jQuery = function( selector, context ) ),但是最后都相当于挂载到了 jQuery.fn.init.prototype,即相当于挂载到了一开始的jQuery 函数返回的对象上,即挂载到了我们最终使用的jQuery对象上。
这个过程非常的绕,金玉其外“败絮”其中啊!
3.2 jQuery.fn.init
jQuery.fn.init的功能是对传进来的selector参数进行分析,进行各种不同的处理,然后生成jQuery对象。
类型(selector)
处理方式
DOM元素
包装成jQuery对象,直接返回
body(优化)
从document.body读取
单独的HTML标签
document.createElement
HTML字符串
document.createDocumentFragment
#id
document.getElementById
选择器表达式
$(…).find
函数
注册到dom ready的回调函数
3.3 jQuery.extend = jQuery.fn.extend
// 合并两个或更多对象的属性到第一个对象中,jQuery后续的大部分功能都通过该函数扩展 
// 通过jQuery.fn.extend扩展的函数,大部分都会调用通过jQuery.extend扩展的同名函数 
// 如果传入两个或多个对象,所有对象的属性会被添加到第一个对象target 
// 如果只传入一个对象,则将对象的属性添加到jQuery对象中。 
// 用这种方式,我们可以为jQuery命名空间增加新的方法。可以用于编写jQuery插件。 
// 如果不想改变传入的对象,可以传入一个空对象:$.extend({}, object1, object2); 
// 默认合并操作是不迭代的,即便target的某个属性是对象或属性,也会被完全覆盖而不是合并 
// 第一个参数是true,则会迭代合并 
// 从object原型继承的属性会被拷贝 
// undefined值不会被拷贝 
// 因为性能原因,JavaScript自带类型的属性不会合并 
// jQuery.extend( target, [ object1 ], [ objectN ] ) 
// jQuery.extend( [ deep ], target, object1, [ objectN ] ) 
jQuery.extend = jQuery.fn.extend = function() { 
var options, name, src, copy, copyIsArray, clone, 
target = arguments[0] || {}, 
i = 1, 
length = arguments.length, 
deep = false; 
// Handle a deep copy situation 
// 如果第一个参数是boolean型,可能是深度拷贝 
if ( typeof target === "boolean" ) { 
deep = target; 
target = arguments[1] || {}; 
// skip the boolean and the target 
// 跳过boolean和target,从第3个开始 
i = 2; 
} 
// Handle case when target is a string or something (possible in deep copy) 
// target不是对象也不是函数,则强制设置为空对象 
if ( typeof target !== "object" && !jQuery.isFunction(target) ) { 
target = {}; 
} 
// extend jQuery itself if only one argument is passed 
// 如果只传入一个参数,则认为是对jQuery扩展 
if ( length === i ) { 
target = this; 
--i; 
} 
for ( ; i < length; i++ ) { 
// Only deal with non-null/undefined values 
// 只处理非空参数 
if ( (options = arguments[ i ]) != null ) { 
// Extend the base object 
for ( name in options ) { 
src = target[ name ]; 
copy = options[ name ]; 
// Prevent never-ending loop 
// 避免循环引用 
if ( target === copy ) { 
continue; 
} 
// Recurse if we're merging plain objects or arrays 
// 深度拷贝且值是纯对象或数组,则递归 
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { 
// 如果copy是数组 
if ( copyIsArray ) { 
copyIsArray = false; 
// clone为src的修正值 
clone = src && jQuery.isArray(src) ? src : []; 
// 如果copy的是对象 
} else { 
// clone为src的修正值 
clone = src && jQuery.isPlainObject(src) ? src : {}; 
} 
// Never move original objects, clone them 
// 递归调用jQuery.extend 
target[ name ] = jQuery.extend( deep, clone, copy ); 
// Don't bring in undefined values 
// 不能拷贝空值 
} else if ( copy !== undefined ) { 
target[ name ] = copy; 
} 
} 
} 
} 
// Return the modified object 
// 返回更改后的对象 
return target; 
};

未完待续
Javascript 相关文章推荐
前端开发部分总结[兼容性、DOM操作、跨域等](持续更新)
Mar 04 Javascript
基于jQuery实现的百度导航li拖放排列效果,即时更新数据库
Jul 31 Javascript
js相册效果代码(点击创建即可)
Apr 16 Javascript
JS常用表单验证方法总结
May 22 Javascript
基于jQuery插件实现点击小图显示大图效果
May 11 Javascript
vue+vuex+axios实现登录、注册页权限拦截
Mar 09 Javascript
node中modules.exports与exports导出的区别
Jun 08 Javascript
基于vue、react实现倒计时效果
Aug 26 Javascript
浅谈微信小程序列表埋点曝光指南
Oct 15 Javascript
React Hooks 实现和由来以及解决的问题详解
Jan 17 Javascript
ElementUI 修改默认样式的几种办法(小结)
Jul 29 Javascript
基于vuex实现购物车功能
Jan 10 Vue.js
jQuery源码分析-02正则表达式 RegExp 常用正则表达式
Nov 14 #Javascript
jQuery源码分析-01总体架构分析
Nov 14 #Javascript
js Form.elements[i]的使用实例
Nov 13 #Javascript
jquery中使用ajax获取远程页面信息
Nov 13 #Javascript
JQuery模板插件 jquery.tmpl 动态ajax扩展
Nov 10 #Javascript
jBox 2.3基于jquery的最新多功能对话框插件 常见使用问题解答
Nov 10 #Javascript
Javascript中的isNaN函数使用说明
Nov 10 #Javascript
You might like
PHP中英混合字符串截取函数代码
2011/07/17 PHP
PHP ignore_user_abort函数详细介绍和使用实例
2014/07/15 PHP
php文件操作相关类实例
2015/06/18 PHP
PHP 读取文本文件内容并分页显示
2016/01/02 PHP
PHP使用curl函数发送Post请求的注意事项
2016/11/26 PHP
PHP设计模式之装饰器模式实例详解
2018/02/07 PHP
ie focus bug 解决方法
2009/09/03 Javascript
JavaScript Event学习补遗 addEventSimple
2010/02/11 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(三)情景对话中仿打字机输出文字
2013/01/23 Javascript
jquery插件tytabs.jquery.min.js实现渐变TAB选项卡效果
2015/08/25 Javascript
JavaScript常用函数工具集:lao-utils
2016/03/01 Javascript
JavaScript获取图片像素颜色并转换为box-shadow显示
2016/03/11 Javascript
原生js实现百叶窗效果及原理介绍
2016/04/12 Javascript
ElementUI多个子组件表单的校验管理实现
2019/11/07 Javascript
[01:01:25]DOTA2上海特级锦标赛B组资格赛#2 Fnatic VS Spirit第三局
2016/02/27 DOTA
可用于监控 mysql Master Slave 状态的python代码
2013/02/10 Python
利用一个简单的例子窥探CPython内核的运行机制
2015/03/30 Python
python读取TXT到数组及列表去重后按原来顺序排序的方法
2015/06/26 Python
Python 专题五 列表基础知识(二维list排序、获取下标和处理txt文本实例)
2017/03/20 Python
详解python并发获取snmp信息及性能测试
2017/03/27 Python
python3 dict ndarray 存成json,并保留原数据精度的实例
2019/12/06 Python
jupyter notebook 使用过程中python莫名崩溃的原因及解决方式
2020/04/10 Python
python之随机数函数的实现示例
2020/12/30 Python
Python自动化测试基础必备知识点总结
2021/02/07 Python
Python中使用Selenium环境安装的方法步骤
2021/02/22 Python
英文自我鉴定
2013/12/10 职场文书
母亲追悼会答谢词
2014/01/27 职场文书
献爱心捐款倡议书
2014/05/14 职场文书
小数乘法教学反思
2016/02/22 职场文书
《学会生存》读后感3篇
2019/12/09 职场文书
浅谈Python中的函数(def)及参数传递操作
2021/05/25 Python
python实现Nao机器人的单目测距
2021/09/04 Python
mysql中数据库覆盖导入的几种方式总结
2022/03/25 MySQL
python实现学员管理系统(面向对象版)
2022/06/05 Python
ConditionalOnProperty配置swagger不生效问题及解决
2022/06/14 Java/Android
Win11控制面板快捷键是什么?Win11打开控制面板的方法汇总
2022/07/07 数码科技