当为 Function
时,调用的其实调用了两次 not
方法,负负得正。关于 not
方法,下面马上会看到。
当为一般的选择器时,调用的是filter
方法,filter
的回调函数调用了 matches
,将符合 selector
的元素返回,并包装成 zepto
对象返回。
.not()
not: function(selector) {
var nodes = []
if (isFunction(selector) && selector.call !== undefined)
this.each(function(idx) {
if (!selector.call(this, idx)) nodes.push(this)
})
else {
var excludes = typeof selector == 'string' ? this.filter(selector) :
(likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector)
this.forEach(function(el) {
if (excludes.indexOf(el) < 0) nodes.push(el)
})
}
return $(nodes)
}
not
方法是将集合中不符合条件的元素查找出来。
not
方法的方法有三种调用方式:
not(selector) ? collection
not(collection) ? collection
not(function(index){ ... }) ? collection
当 selector
为 Function
,并且有 call
方法时(isFunction(selector) && selector.call !== undefined
),相关的代码如下:
this.each(function(idx) {
if (!selector.call(this, idx)) nodes.push(this)
})
调用 each
方法,并且在 selector
函数中,可以访问到当前的元素和元素的索引。如果 selector
函数的值取反后为 true
,则将相应的元素放入 nodes
数组中。
当 selector
不为 Function
时, 定义了一个变量 excludes
,这个变量来用接收需要排除的元素集合。接下来又是一串三元表达式(zepto的特色啊)
typeof selector == 'string' ? this.filter(selector)
当 selector
为 string
时,调用 filter
,找出所有需要排除的元素
(likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector)
这段我刚开始看时,有点困惑,主要是不明白 isFunction(selector.item)
这个判断条件,后来查了MDN文档HTMLCollection.item,才明白 item
是 HTMLCollection
的一个方法,这个三元表达式的意思是,如果是 HTMLCollection
,则调用 slice.call
得到一个纯数组,否则返回 zepto
对象。
this.forEach(function(el) {
if (excludes.indexOf(el) < 0) nodes.push(el)
})
遍历集合,如果元素不在需要排除的元素集合中,将该元素 push
进 nodes
中。
not
方法最终返回的也是 zepto
对象。
.is()
is: function(selector) {
return this.length > 0 && zepto.matches(this[0], selector)
}
判断集合中的第一个元素是否匹配指定的选择器。
代码也比较简单了,选判断集合不为空,再调用 matches
看第一个元素是否匹配。
.find()
find: function(selector) {
var result, $this = this
if (!selector) result = $()
else if (typeof selector == 'object')
result = $(selector).filter(function() {
var node = this
return emptyArray.some.call($this, function(parent) {
return $.contains(parent, node)
})
})
else if (this.length == 1) result = $(zepto.qsa(this[0], selector))
else result = this.map(function() { return zepto.qsa(this, selector) })
return result
}
find
是查找集合中符合选择器的所有后代元素,如果给定的是 zepto
对象或者 dom
元素,则只有他们在当前的集合中时,才返回。
fid
有三种调用方式,如下:
find(selector) ? collection
find(collection) ? collection
find(element) ? collection
if (!selector) result = $()
如果不传参时,返回的是空的 zepto
对象。
else if (typeof selector == 'object')
result = $(selector).filter(function() {
var node = this
return emptyArray.some.call($this, function(parent) {
return $.contains(parent, node)
})
})
如果传参为 object
时,也就是 zepto
对象collection
和dom
节点 element
时,先将 selector
包裹成 zepto
对象,然后对这个对象过滤,返回当前集合子节点中所包含的元素($.contains(parent, node)
)。
else if (this.length == 1) result = $(zepto.qsa(this[0], selector))
如果当前的集合只有一个元素时,直接调用 zepto.qsa
方法,取出集合的第一个元素 this[0]
作为 qsa
的第一个参数。关于 qsa
方法,已经在《读Zepto源码之神奇的$》分析过了。其实就是获取第一个元素的所有后代元素。
else result = this.map(function() { return zepto.qsa(this, selector) })
否则,调用 map
方法,对集合中每个元素都调用 qsa
方法,获取所有元素的后代元素。这个条件其实可以与上一个条件合并的,分开应该是为了性能的考量。
.has()
has: function(selector) {
return this.filter(function() {
return isObject(selector) ?
$.contains(this, selector) :
$(this).find(s