读Zepto源码之集合操作
接下来几个篇章,都会解读 zepto 中的跟 dom 相关的方法,也即源码 $.fn 对象中的方法。
读Zepto源码系列文章已经放到了github上,欢迎star: reading-zepto
源码版本
本文阅读的源码为 zepto1.2.0
.forEach()
forEach: emptyArray.forEach
因为 zepto 的 dom 集合是类数组,所以这里只是简单地复制了数组的 forEach 方法。
具体的 forEach 的用法见文档:Array.prototype.forEach()
.reduce()
reduce: emptyArray.reduce
简单地复制了数组的 reduce 方法。
具体的 reduce 的用法见文档:Array.prototype.reduce()
.push()
push: emptyArray.push
简单地复制了数组的 push 方法。
具体的 push 的用法见文档:Array.prototype.push()
.sort()
sort: emptyArray.sort
简单地复制了数组的 sort 方法。
具体的 sort 的用法见文档:Array.prototype.sort()
.splice()
splice: emptyArray.splice
简单地复制了数组的 splice 方法。
具体的 splice 的用法见文档:Array.prototype.splice()
.indexOf()
indexOf: emptyArray.indexOf
简单地复制了数组的 indexOf 方法。
具体的 indexOf 的用法见文档:Array.prototype.indexOf()
.get()
get: function(idx) {
return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length]
},
这个方法用来获取指定索引值的元素。
不传参(idx === undefined)时,不传参调用数组的 slice 方法,将集合中的所有元素返回。
当传递的参数大于或等于零(idx)时,返回相应索引值的元素 this[idx] ,如果为负数,则倒数返回this.[idx + this.length]。
例如 $('li').get(-1) 返回的是倒数第1个元素,也即最后一个元素
.toArray()
toArray: function() { return this.get() }
toArray 方法是将元素的类数组变成纯数组。toArray 内部不传参调用 get 方法,上面已经分析了,当不传参数时,get 方法调用的是数组方法 slice, 返回的自然就是纯数组了。
.size()
size: function() {
return this.length
}
size 方法返回的是集合中的 length 属性,也即集合中元素的个数。
.concat()
concat: function() {
var i, value, args = []
for (i = 0; i < arguments.length; i++) {
value = arguments[i]
args[i] = zepto.isZ(value) ? value.toArray() : value
}
return concat.apply(zepto.isZ(this) ? this.toArray() : this, args)
},
数组中也有对应的 concat 方法,为什么不能像上面的方法那样直接调用呢?
这是因为 $.fn 其实是一个类数组对象,并不是真正的数组,如果直接调用 concat 会直接把整个 $.fn 当成数组的一个 item 合并到数组中。
for (i = 0; i < arguments.length; i++) {
value = arguments[i]
args[i] = zepto.isZ(value) ? value.toArray() : value
}
这段是对每个参数进行判断,如果参数是 zepto 的集合(zepto.isZ(value)),就先调用 toArray 方法,转换成纯数组。
return concat.apply(zepto.isZ(this) ? this.toArray() : this, args)
这段同样对 this 进行了判断,如果为 zepto 集合,也先转换成数组。所以调用 concat 后返回的是纯数组,不再是 zepto 集合。
.map()
map: function(fn) {
return $($.map(this, function(el, i) { return fn.call(el, i, el) }))
}
map 方法的内部调用的是 zepto 的工具函数 $.map ,这在之前已经在《读Zepto源码之工具函数》做过了分析。
return fn.call(el, i, el)
map 方法对回调也做了包装,call 的第一个参数为 el ,因此可以在 map 的回调中通过 this 来拿到每个元素。
map 方法对 $.map 返回的数组调用了 $() 方法,将返回的数组再次包装成 zepto 对象,因此调用 map 方法后得到的数组,同样具有 zepto 集合中的方法。
.slice()
slice: function() {
return $(slice.apply(this, arguments))
}
slice 同样没有直接用数组的原生方法,也像 map 方法一样,将返回的数组再次包装成 zepto 对象。
.each()
each: function(callback) {
emptyArray.every.call(this, function(el, idx) {
return callback.call(el, idx, el) !== false
})
return this
},
zepto 的 each 方法比较巧妙,在方法内部,调用的其实是数组的 every 方法,every 遇到 false 时就会中止遍历,zepto 也正是利用 every 这种特性,让 each 方法也具有了中止遍历的能力,当 callback 返回的值为布尔值 false 时,中止遍历,注意这里用了 !==,因为 callback 如果没有返回值时,得到的值会是 undefined ,这种情况是需要排除的。
同样,each 的回调中也是可以用 this 拿到每个元素的。
注意,each 方法最后返回的是 this, 所以在 each 调用完后,还可以继续调用 集合中的其他方法,这就是 zepto 的链式调用,这个跟 map 方法中返回 zepto 集合的原理差不多,只不过 each 返回的是跟原来一样的集合,map 方法返回的是映射后的集合。
.add()
add: function(selector, context) {
return $(uniq(this.concat($(selector, context))))
}
add 可以传递两个参数,selector 和 context ,即选择器和上下文。
add 调用 $(selector, context) 来获取符合条件的集合元素,这在上篇文章《读Zepto源码之神奇的$》已经有详细的论述。
然后调用 concat 方法来合并两个集合,用内部方法 uniq 来过滤掉重复的项,uniq 方法在《读Zepto源码之内部方法》已经有论述。最后也是返回一个 zepto 集合。
系列文章
参考
- Array.prototype.forEach()
- Array.prototype.reduce()
- Array.prototype.push()
- Array.prototype.sort()
- Array.prototype.splice()
- Array.prototype.indexOf()
License
作者:对角另一面
读Zepto源码之集合操作的更多相关文章
- 读 Zepto 源码之集合元素查找
这篇依然是跟 dom 相关的方法,侧重点是跟集合元素查找相关的方法. 读Zepto源码系列文章已经放到了github上,欢迎star: reading-zepto 源码版本 本文阅读的源码为 zept ...
- 读Zepto源码之样式操作
这篇依然是跟 dom 相关的方法,侧重点是操作样式的方法. 读Zepto源码系列文章已经放到了github上,欢迎star: reading-zepto 源码版本 本文阅读的源码为 zepto1.2. ...
- 读Zepto源码之属性操作
这篇依然是跟 dom 相关的方法,侧重点是操作属性的方法. 读Zepto源码系列文章已经放到了github上,欢迎star: reading-zepto 源码版本 本文阅读的源码为 zepto1.2. ...
- 读Zepto源码之操作DOM
这篇依然是跟 dom 相关的方法,侧重点是操作 dom 的方法. 读Zepto源码系列文章已经放到了github上,欢迎star: reading-zepto 源码版本 本文阅读的源码为 zepto1 ...
- 读Zepto源码之Event模块
Event 模块是 Zepto 必备的模块之一,由于对 Event Api 不太熟,Event 对象也比较复杂,所以乍一看 Event 模块的源码,有点懵,细看下去,其实也不太复杂. 读Zepto源码 ...
- 读Zepto源码之Callbacks模块
Callbacks 模块并不是必备的模块,其作用是管理回调函数,为 Defferred 模块提供支持,Defferred 模块又为 Ajax 模块的 promise 风格提供支持,接下来很快就会分析到 ...
- 读Zepto源码之Deferred模块
Deferred 模块也不是必备的模块,但是 ajax 模块中,要用到 promise 风格,必需引入 Deferred 模块.Deferred 也用到了上一篇文章<读Zepto源码之Callb ...
- 读Zepto源码之Ajax模块
Ajax 模块也是经常会用到的模块,Ajax 模块中包含了 jsonp 的现实,和 XMLHttpRequest 的封装. 读 Zepto 源码系列文章已经放到了github上,欢迎star: rea ...
- 读Zepto源码之Selector模块
Selector 模块是对 Zepto 选择器的扩展,使得 Zepto 选择器也可以支持部分 CSS3 选择器和 eq 等 Zepto 定义的选择器. 在阅读本篇文章之前,最好先阅读<读Zept ...
随机推荐
- 云计算+SaaS+业务开发平台=JSAAS云平台
我关注Google的代码托管.Open API,我也关注Oracle会把MYSQL怎么样云数据库化,我也虚拟化技术多实例化独立的数据库,我也关注facebook的平台插件应用架构,我也关注salesf ...
- Linux命令的复习总结学习
1.-------------------------linux系统介绍------------------------------------------------------- Linux是一套 ...
- POST与GET
面试如果被问到这个问题,相信很多人都是会心一笑,答案随口而来: 1.GET在浏览器回退时是无害的,而POST会再次提交请求. 2.GET请求会被浏览器主动cache,而POST不会,除非手动设置. 3 ...
- Linux必备 -- 如何在Mac OS 使用VMware 安装Linux
Linux简介 Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CPU的操作系统.它能运行主要的UNIX工具软件.应用程序和网络协 ...
- MySQL的loop循环函数的demo
使用的工具是Navicat for MySQL. 在MySQL中用函数实现在字符串一后面循环拼接n个字符串二 delimiter $$ drop function if exists fun_addS ...
- 最新windows 0day漏洞利用
利用视屏:https://v.qq.com/iframe/player.html?vid=g0393qtgvj0&tiny=0&auto=0 使用方法 环境搭建 注意,必须安装32位p ...
- 记一次 Newtonsoft.Json 巧妙的用法(C#)
数据添加的功能 有一个表格提交数据如下: 是否选择和文本值.分开保存到数据库太麻烦.取得时候也麻烦 想到了存成json数据.一个字段就可以了. html代码: <table class=&quo ...
- jquery控制图片切换
这种js现在用的很多.同时网上的js代码页很多.我直接从网上当了一个来用:代码如下: html <div class="bannerbox"> ...
- T-SQL编程语句
书接上回 一起学习下SQL中的表连接 一般情况下咱们会使用鼠标去进行表连接操作,那针对于像我比较懒的并且眼盲的,不喜欢来回切换,咱们就用到了点T-SQL表连接语句 一般情况咱们从两个表中查出来相似的内 ...
- 更改oracle字符集
修改oracle字符集 方法/步骤 oracle数据库的字符集更改 A.oracle server 端 字符集查询 select userenv('language') from dual 其中 ...