2.2.6 延续 -- 迭代器
在 jQuery 框架中,jQuery 对象是一个很奇怪的概念,具有多重身份,所以很多初学者一听说 jQuery 对象就感觉很是不解,误以为它是 John Resig 制造的新概念。我们可以对jQuery 对象进行如下分解。
第一,jQuery 对象是一个数据集合,它不是一个个体对象。因此,你无法直接使用 JavaScript 的方法来操作它。
第二,jQuery 对象实际上就是一个普通的对象,因为它是通过 new 运算符创建的一个新的实例对象。它可以继承原型方法或属性,同时也拥有 Object 类型的方法和属性。
第三,jQuery 对象包含数组特性,因为它赋值了数组元素,以数组结构存储返回的数据。我们可以以 JavaScript 的概念理解 jQuery 对象,例如下面的示例。
[html]view
plain
上面的 jQuery 对象就是一个典型的 jQuery 对象,jQuery 对象的结构就是按这种形式设计的。可以说,jQuery
对象就是对象和数组的混合体,但是它不拥有数组的方法,因为它的数组结构是人为附加的,也就是说它不是 Array 类型数据,而是 Object 类型数据。
第四,jQuery 对象包含的数据都是 DOM 元素,是通过数组形式存储的,即通过 jQuery[n] 形式获取。同时 jQuery 对象又定义了几个模仿 Array 基本特性的属性,如 length 等。
所以,jQuery 对象是不允许直接操作的,只有分别读取它包含的每一个 DOM 元素,才能实现各种操作,如插入、删除、嵌套、赋值和读写 DOM 元素属性等。
那么如何实现直接操作 jQuery 对象中的 DOM 元素呢?
在实际应用中,我们可以看到类似下面的 jQuery 用法。
$("div").html()
也就是直接在 jQuery 对象上调用 html(),并实现操作 jQuery 包含的所有 DOM 元素。那么这个功能是怎么实现的呢?
jQuery 定义了一个工具函数 each(),利用这个工具可以遍历 jQuery 对象中所有的 DOM 元素,并把需要操作的内容封装到一个回调函数中,然后通过在每个 DOM 元素上调用这个回调函数即可。实现代码如下所示,演示效果如图 2.2 所示。
[html]view
plain
在上面的示例中,通过先为自己的 jQuery 对象绑定 html() 方法,然后利用 jQuery() 选择器获取页面中所有的 div 元素,再调用 html() 方法,为所有匹配的元素插入 HTML 源码。
注意,在上面的代码中,each() 函数的当前作用对象是 jQuery 对象,故 this 指向当前 jQuery 对象,即 this 表示一个集合对象;而在 html() 方法中,由于 each() 函数是在指定 DOM 元素上执行的,所以该函数内的 this 指针指向的是当前 DOM 元素对象,即 this 表示一个元素。
2.2.7 延续 -- 功能扩展
根据一般设计习惯,如果要为 jQuery 或者 jQuery.prototype 添加函数或方法,可以直接通过点语法实现,或者在 jQuery.prototype 对象结构中增加一个属性即可。但是,如果分析 jQuery 框架的源代码,你会发现它是通过 extend() 函数来实现功能扩展的。例如,下面两段代码都是 jQuery 框架通过 extend() 函数来扩展功能的。
jQuery.extend({ // 扩展工具函数
noConflict: function(deep){},
isFunction: function(obj){},
isArray: function(obj){},
isXMLDoc: function(elem){},
globalEval: function(data){}
});
或者
jQuery.fn.extend({// 扩展 jQuery 对象方法
show: function(speed, callback){},
hide: function(speed, callback){},
toggle: function(fn, fn2){},
fadeTo: function(speed, to, callback){},
animate: function(prop, speed, easing, callback){},
stop: function(clearQueue, gotoEnd){}
});
这样做的好处是什么呢?