《jQuery源码解析》读书笔记(第二章:构造jQuery对象)
2015-11-12 16:10
691 查看
第2章 构造jquery对象 8
jQuery对象是一个类数组对象,含有
连续的整形属性
length属性
大量的
jQuery方法
2.1 构造函数
jquery()8
jQuery很有意思的一点是,它的方法定义很强大,会根据不同的参数情况执行不同的功能。
构造函数
jQuery()有 7 种用法。
2.1.1
jquery( selector [, context] )9
用法
如果传入一个字符串参数,
jQuery会检查这个字符串是选择器还是
HTML代码
如果是选择器,则遍历文档
如果有匹配的元素,返回匹配的封装了匹配的
DOM元素的
jQuery对象
如果没有匹配的元素,则返回一个空的
jQuery对象
2.1.2
jquery( html [, ownerdocument] )、jquery( html, props )9
用法
如果传入的参数看起来像一段
HTML代码,那么
jQuery会尝试创建新的
DOM元素,并创建一个封装了此
DOM元素的
jQuery对象
第二个参数
ownerDocument用于指定创建新
DOM对象的文档对象,如果不传入,则默认为当前文档对象
如果
HTML代码是单独一个标签,那么第二个参数还可以是
props,是一个包含了属性、事件的普通对象,设置新创建元素的属性、事件
2.1.3
jquery( element )、jquery( elementarray )10
用法
传入一个
DOM对象或
DOM数组,然后封装这些
DOM为
jQuery对象
2.1.4
jquery( object )10
用法
传入一个普通
JavaScript对象,把该对象封装到
jQuery对象并返回
可以方便的实现自定义事件的绑定和触发
2.1.5
jquery( callback )11
用法
DOM ready事件的回调函数
2.1.6
jquery( jquery object )11
用法
传入一个
jQuery对象,则返回该对象的一个副本,这个副本与原
jQuery对象引用相同的
DOM元素
2.1.7
jquery()11
用法
不传入任何一个参数,则返回一个空的
jQuery对象
可以用来复用
jQuery对象,例如,创建一个空的
jQuery对象,然后在需要的时候手动修改其中的元素,再调用
jQuery方法,从而避免重复创建
jQuery对象
2.2 总体结构 11
(function(window, undefined) { // 构造 jQuery 对象 var jQuery = (function() { var jQuery = function(selector, context) { return new jQuery.fn.init(selector, context, rootjQuery); }; // 一堆局部变量声明 // ... jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function(selector, context, rootjQuery) { } // 一堆原型属性和方法 }; jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function() {}; jQuery.extend({ // 一堆静态属性和方法 }); return jQuery; })(); // 工具方法 Utilities // 回调函数列表 Callbacks Object // 异步队列 Defferred Object // 浏览器功能测试 Support // 数据缓存 Data // 队列 Queue // 属性操作 Attributes // 事件系统 Events // 选择器 Sizzle // DOM遍历 Traversing // 样式操作 CSS(计算样式、内联样式) // 异步请求 Ajax // 动画 Effects // 坐标 Offset、尺寸 Dimensions window.jQuery = window.$ = jQuery; })(window);
以上内容,有几个要点:
jQuery的定义部分,为什么要用自调用匿名函数包裹?
减少与其他模块的耦合,体现高内聚低耦合的思想
jQuery、
jQuery.fn.init的
prototype都被覆盖了
jQuery、
jQuery.fn.init这两个方法的
prototype都指向了
jQuery.prototype
好处是
jQuery和
jQuery.prototype.init的实例都可以访问构造函数
jQuery()的原型属性和方法。
用图表示即:
new jQuery() ---> jQuery.prototype ----> 同一个对象 new jQuery.prototype.init() ---> jQuery.prototype.init.prototype
为什么要增加一个函数
jQuery.fn.init?
1、对返回对象的要求:该对象需要能访问
jQuery原型上的方法和属性。
2、一般情况下返回的是
jQuery的实例,但如果返回的代码是
return new jQuery(),会形成死循环
3、因此构建一个新函数,该函数的实例也能访问
jQuery原型上的方法和属性
为什么要在构造函数
jQuery()内部用运算符
new创建并返回另一个构造函数的实例?
创建一个实例的方式是
new后面跟一个构造函数,如果构造函数有返回值,运算符
new所创建的对象会被丢弃,返回值将作为
new表达式的值
jQuery利用了这一特性,省去了构造函数
jQuery()之前的运算符
new
为了书写方便,为构造函数定义了别名
$
2.3
jquery.fn.init( selector, context, rootjquery )13
构造函数
jquery.fn.init()负责解析参数
selector和
context的类型,并执行相应的逻辑,返回
jquery.fn.init()的实例。它有12个有效分支
.2.3.1 12个分支 13
2.3.2 源码分析 14
2.3.3 小结 21
2.4
jquery.buildfragment( args, nodes, scripts )22
2.4.1 实现原理 22
2.4.2 源码分析 22
2.4.3 小结 26
2.5
jquery.clean( elems, context, fragment, scripts )27
2.5.1 实现原理 27
2.5.2 源码分析 27
2.5.3 小结 39
2.6
jquery.extend()、jquery.fn.extend()40
2.6.1 如何使用 40
二者是一样的功能:
jQuery.extend = jQuery.fn.extend = function()
也就是说,
jQuery对象和
jQuery的实例对象都有
extend方法了
语法
jQuery.extend([deep],target,object1[,objectN])
jQuery.fn.extend([deep],target,object1[,objectN])
参数
deep
是可选的布尔值,表示是否进行深度合并(即递归合并),默认是不递归的,即后面参数的属性的会覆盖第一个参数的同名属性。如果是
true,表示进行深度合并,合并过程是递归的。
target
目标对象
objectN
源对象,所有源对象的属性都会合并到目标对象
如果只有一个参数
那么参数
target将被忽略,
jQuery或
jQuery.fn被当做目标对象,用这种方式可以在
jQuery或
jQuery.fn上添加新的属性和方法
2.6.2 源码分析 40
2.7 原型属性和方法 43
以下属性和方法均在下方代码块中定义
jQuery.fn = jQuery.prototype = { 原型属性和方法 }
也就是说,
jQuery的实例有这些属性和方法
2.7.1
.selector、.jquery、.length、.size()44
源码
selector: '', // 版本号 jquery: '1.7.1', // jQuery 对象中元素的个数,初始化为 0 length: 0, // 同 length,不建议使用 size: function() { return this.length; },
selector
介绍
当前
jQuery对象的选择器,主要用来调试,与实际选择器不一定匹配
源码
`jquery`: 当前`jQuery`的版本号 `length`:jQuery 对象中元素的个数,初始化为 0 `size`:同 length,不建议使用,因为有函数调用开销
2.7.2
.toarray()、.get( [index] )45
toArray
slice = Array.prototype.slice toArray: function() { return slice.call(this, 0); }
小技巧:借鸡下蛋
利用
Array.prototype.slice方法将
jQuery对象转为数组,形成方法
toArray。
slice方法里的
this,可以是数组,也可以是类数组。
get
源码:
return num == null ? this.toArray() ? (num < 0 ? this[this.length + num] : this[num])
这样就可以支持: 1、参数为空;2、下标为负数。
2.7.3
.each( function(index, element) )、jquery.each( collection, callback (indexinarray, valueofelement) )46
.each
功能介绍
1、遍历当前
jQuery对象,并在每个对象上执行回调函数
2、回调函数参数是索引(从
0开始)和当前对象
3、最重要的一点是,回调函数中的
this总是指向当前元素
4、在回调函数中返回
false可以终止遍历
实现技巧
在源码中,它通过调用
jQuery.each方法来实现,又一个借鸡生蛋的应用。
jQuery.each
源码在
627~666行,就不贴在这里了
源码实现的总体思路
功能上,可以遍历(类)数组和对象(包括函数)
可以自定义回调函数的参数,如果不自定义,则默认给回调函数传
index, element的参数
小技巧
判断是否是对象:
isObj == object.length === undefined || jQuery.isFunction(object)
遍历对象,用
for in
遍历数组,用
for循环
执行、判断写在同一句
if(callback.call(object[i], i, object[i++]) === false){ break; }
break可以跳出
for in和
for循环
2.7.4
.map( callback(index, domelement) )、jquery.map( arrayorobject, callback(value, indexorkey) )47
2.7.5
.pushstack( elements, name, arguments )49
2.7.6
.end()51
功能描述
核心代码:
return this.prevObject || this.constructor(null)
如果是:
$(ul.first).find('.foo').css(..).end().find('.bar')
2.7.7
.eq( index )、.first()、.last()、.slice( start [, end] )51
.eq
eq: function(i) { i = +i; return i === -1 ? this.slice(i) : this.slice(i, i + 1); }
小技巧:如果
i是字符串,把前面加上
+可以把该参数转换为数值
2.7.8
.push( value, ... )、.sort( [orderfunc] )、.splice( start,deletecount, value, ... )52
.push
var foo = $(document); foo.push(document.body); // 2
.sort
var foo = $([33, 4, 1111, 222]); foo.sort(); // [1111, 222, 33, 4] foo.sort(function(a, b) { return a - b; }); // [4, 33, 222, 1111]
2.7.9 小结 53
2.8 静态属性和方法 54
2.8.1
jquery.noconflict( [removeall] )55
看源码即可,绕来绕去的
2.8.2 类型检测:
jquery.isfunction( obj )、
jquery.isarray( obj )、
jquery.iswindow( obj )、
jquery.isnumeric( value )、
jquery.type( obj )、
jquery.isplainobject( object )、
jquery.isemptyobject( object )56
判断类型
核心代码是用了
toString.call(obj)判断,该表达式的值是:
[object Array]、
[object Boolean]、
[object Date]、
[object Function]、
[object Number]、
[object Object]、
[object RegExp]、
[object String]
还有一个小技巧,循环数组:
('Boolean Date Function Number Object RegExp String').split(' ')
isWindow
判断方法是:
obj == obj.window,以前的版本里是:
setInterval in obj
jquery.isplainobject( object )
功能
判断对象是否由
{}或
new Object()创建
返回
false的情况
object可以转为
false
Object.prototype.toString.call(object)返回的不是
[object Object]
object是
DOM元素
object.nodeType非空
object是
window对象
不是由
Object()函数创建,而是由自定义函数创建的,返回
false
含有属性
constructor
是继承属性
是自身属性
如果不含属性
constructor,则一定是
{}创建的对象
没有属性
isPropertyOf
isPropertyOf是
Object原型对象的特有属性
执行时抛出异常。
IE 8/9中,在某些浏览器对象上执行以上检测时会抛出异常,也应该返回
false
返回
true的情况
用
Object.prototype.hasOwnProperty(property)检测对象是否含有该非继承属性
如果该对象没有属性,或所有属性都是非继承属性,则返回
true
jquery.isemptyobject( object )
用
for in遍历自身属性和继承属性
parseFloat(x)可以解析字符串,并返回字符串的第一个数字;如果没有数字,则返回
NaN;如果参数是对象,则自动调用该对象的方法
toString(),得到该对象的字符串表示,然后再解析
2.8.3 解析
json和
xml:
jquery.parsejson( data )、
jquery.parsexml( data )60
jquery.parsejson( data )
解析思路
先尝试用
JSON.parse解析,如果没有该方法,则用
(new Function('return' + data))()解析
其余的是正则表达式匹配字符串之类的东西,在此略过
JSON.parse
解析
json字符串为
json对象
判断方法:
window.JSON && window.JSON.parse
JSON.stringify
解析
json对象为
json字符串
用法1:
JSON.stringify({a: 1, b: 2}); // '{"a": 1, "b": 2}'
用法2:
JSON.stringify({a: 1, b: 2}, function(key, value) { if(key == '') return value; if(key == 'a') return value * 10; if(key == 'b') return undefined; return value; }) // '{"a": 10}'
用法3:
JSON.stringify({a: 1, b: 2}, ['b']); // '{"b": 2}'
用法4:
JSON.stringify({a: 1, b: 2}, null, 4); // '{\n "a": 1\n "b": 2\n}'
2.8.4
jquery.globaleval( code )65
略
2.8.5
jquery.camelcase( string )65
针对
-ms单独做了处理,所有处理函数还是很简洁的
return string.replace(/^-ms-/, 'ms-').replace(/-[a-z]|[0-9]/, function(){...});
2.8.6
jquery.nodename( elem, name )66
dom元素的节点名称:
dom.nodeName
2.8.7
jquery.trim( str )67
书中的思路很清晰,值得一提的是,这个方法里同样用了
String.prototype.trim()方法来借鸡生蛋
另外,在
IE9中,正则
/\s/不能匹配不间断空格
\xA0,但其也被认为是空格。测试是否不识别,用:
/\S/.test('\xA0'),如果是
true,则不能识别
2.8.8 数组操作方法:
jquery.makearray( obj )、jquery.inarray( value, array [, fromindex] )、jquery.merge( first, second )、jquery.grep( array, function(elementofarray, indexinarray) [, invert] )68
jquery.makearray( obj )
学到了一点:
push方法里的
this可以指定为类数组
jquery.inarray( value, array [, fromindex] )
fromIndex是查找的起点
如果浏览器支持数组方法
indexOf,则直接调用,否则就自己写方法
数组的下标有可能是不连续的,所以需要用
i in array来判断是否存在下标
i
值得学习的就是判断了
if($.inArray(element, array) > -1) {}
太繁琐,改进为
if(!!~$.inArray(element, array)) {}
~按位取反,相当于改变符号并且减一,只有当
-1时,
~(-1) == 0
!!用来形成布尔值
jquery.merge( first, second )
这个方法的源码写的挺不错的,值得一看。
其中,把
second认为两种对象处理:
1、数组/类数组(判断依据:有无整数/可转为整数的属性
length,
typeof second.length === 'number')
2、含有连续整形(或可转换为连续整形)的对象,如
{0: 'a', 1: 'b'},从下标
0开始遍历。
最后修正
first.length,因为
first不一定是真正的属性,需要手动维护
length属性。
2.8.9
jquery.guid、jquery.proxy( function, context )72
jquery.proxy( function, context )
这个函数使得某个函数在任何环境下执行时,上下文都是
context,很实用。
而且,它的实现原理是:1、闭包封存上下文
context;2、返回一个新函数,新函数的作用域链上,有闭包内的上下文
context
其他的,看源码即可。
2.8.10
jquery.access( elems, key, value, exec, fn( elem, key, value ), pass )74
2.8.11
jquery.error( message )、
jquery.noop()、
jquery.now()75
略
2.8.12 浏览器嗅探:
jquery.uamatch( ua )、
jquery.browser76
略
2.8.13 小结 77
2.9 总结 77
到这一步,值得将
jQuery的整体结构再回顾一遍了。代码概述在
11页的图上。
(1)构造函数
jQuery()有7种用法,根据参数的不同而不同。
(2)
jQuery.fn.init()方法有
12种用法,根据参数的不同而不同。
(2)原型属性和方法,直接放在
jQuery.fn = jQuery.prototype对象上
(3)静态属性和方法,通过
jQuery.extend({...})放在
jQuery对象上
相关文章推荐
- 《jQuery源码解析》读书笔记(第一章:总体架构)
- 有关jquery jqgrid的一些操作
- js事件委托和jQuery事件绑定on , off , one , bind , unbind , die
- jQuery源码学习3——工具方法篇
- web前端,jquery对元素及属性进行获取,设置,添加,删除
- 怎么选择公司???MVC加jquery-easyui 后端工程师
- JQuery Show()的几种效果 总有一种是你需要的
- jquery控制按钮的禁用与启
- 详解MyEclipse10 安装Spket 1.6.23(支持Extjs4.1.1及jQuery1.8)
- 使用jquery showloading plugin 加载滚动条的方法
- Jquery中$(this)的含义----联系的问题
- 如何将easyui中的jquery.messager.confirm提示框按钮改成中文?
- jQuery-1.9.1源码分析系列(四) 缓存系统
- jQuery中设置form表单中action值的方法
- jQuery中添加自定义或函数方法
- jquery表单序列表转化为json
- Jquery zTree的使用
- JQuery学习系列基础教程
- 备忘篇——jQuery中操作数组
- jquery-ui,弹出,等等各种特效