深入学习jquery源码之filter()与find()
filter(expr|obj|ele|fn)
概述
筛选出与指定表达式匹配的元素集合。
这个方法用于缩小匹配的范围。用逗号分隔多个表达式
参数
expr String
字符串值,包含供匹配当前元素集合的选择器表达式。
jQuery object object
现有的jQuery对象,以匹配当前的元素。
element Expression
一个用于匹配元素的DOM元素。
function(index) Function
一个函数用来作为测试元素的集合。它接受一个参数index,这是元素在jQuery集合的索引。在函数, this指的是当前的DOM元素。
保留带有select类的元素
Hello
Hello Again
And Again
$("p").filter(".selected")
[ And Again
]
保留第一个以及带有select类的元素
Hello
Hello Again
And Again
$("p").filter(".selected, :first")
[ Hello
, And Again
]
保留子元素中不含有ol的元素。
- Hello
How are you?
$("p").filter(function(index) {
return $("ol", this).length == 0;
});
[ How are you?
]
find(expr|obj|ele)
概述
搜索所有与指定表达式匹配的元素。这个函数是找出正在处理的元素的后代元素的好方法。
所有搜索都依靠jQuery表达式来完成。这个表达式可以使用CSS1-3的选择器语法来写。
参数
expr String
用于查找的表达式
jQuery object object
一个用于匹配元素的jQuery对象
element DOMElement
一个DOM元素
从所有的段落开始,进一步搜索下面的span元素。与$("p span")相同。
Hello, how are you?
$("p").find("span")
[ Hello ]
jquery源码
jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.pseudos;
jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;
var Sizzle =
(function (window) {
var i,
support,
Expr,
getText,
isXML,
tokenize,
compile,
select,
outermostContext,
sortInput,
hasDuplicate,
// Local document vars
setDocument,
document,
docElem,
documentIsHTML,
rbuggyQSA,
rbuggyMatches,
matches,
contains,
// Instance-specific data
expando = "sizzle" + 1 * new Date(),
preferredDoc = window.document,
dirruns = 0,
done = 0,
classCache = createCache(),
tokenCache = createCache(),
compilerCache = createCache(),
sortOrder = function (a, b) {
if (a === b) {
hasDuplicate = true;
}
return 0;
},
// General-purpose constants
MAX_NEGATIVE = 1 +~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i")
},
rinputs = /^(?:input|select|textarea|button)$/i,
rheader = /^h\d$/i,
rnative = /^[^{]+\{\s*\[native \w/,
// Easily-parseable/retrievable ID or TAG or CLASS selectors
rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
rsibling = /[+~]/,
rescape = /'|\\/g,
// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
runescape = new RegExp("\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig"),
funescape = function (_, escaped, escapedWhitespace) {
var high = "0x" + escaped - 0x10000;
// NaN means non-codepoint
// Support: Firefox> 10 | 0xD800, high & 0x3FF | 0xDC00);
},
// Used for iframes
// See setDocument()
// Removing the function wrapper causes a "Permission Denied"
// error in IE
unloadHandler = function () {
setDocument();
};
// Optimize for push.apply( _, NodeList )
try {
push.apply(
(arr = slice.call(preferredDoc.childNodes)),
preferredDoc.childNodes
);
// Support: Android 0;
};
return Sizzle;
})(window);
var risSimple = /^.[^:#\[\.,]*$/;
// Implement the identical functionality for filter and not
function winnow(elements, qualifier, not) {
if (jQuery.isFunction(qualifier)) {
return jQuery.grep(elements, function (elem, i) {
/* jshint -W018 */
return !!qualifier.call(elem, i, elem) !== not;
});
}
if (qualifier.nodeType) {
return jQuery.grep(elements, function (elem) {
return (elem === qualifier) !== not;
});
}
if (typeof qualifier === "string") {
if (risSimple.test(qualifier)) {
return jQuery.filter(qualifier, elements, not);
}
qualifier = jQuery.filter(qualifier, elements);
}
return jQuery.grep(elements, function (elem) {
return (jQuery.inArray(elem, qualifier) >= 0) !== not;
});
}
jQuery.filter = function (expr, elems, not) {
var elem = elems[0];
if (not) {
expr = ":not(" + expr + ")";
}
return elems.length === 1 && elem.nodeType === 1 ?
jQuery.find.matchesSelector(elem, expr) ? [elem] : [] :
jQuery.find.matches(expr, jQuery.grep(elems, function (elem) {
return elem.nodeType === 1;
}));
};
jQuery.fn = jQuery.prototype = {
// The current version of jQuery being used
jquery: version,
constructor: jQuery,
// Start with an empty selector
selector: "",
// The default length of a jQuery object is 0
length: 0,
toArray: function () {
return slice.call(this);
},
// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function (elems) {
// Build a new jQuery matched element set
var ret = jQuery.merge(this.constructor(), elems);
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
// Return the newly-formed element set
return ret;
}
// For internal use only.
// Behaves like an Array's method, not like a jQuery method.
push: push,
sort: deletedIds.sort,
splice: deletedIds.splice
};
jQuery.fn.extend({
find: function (selector) {
var i,
ret = [],
self = this,
len = self.length;
if (typeof selector !== "string") {
return this.pushStack(jQuery(selector).filter(function () {
for (i = 0; i < len; i++) {
if (jQuery.contains(self[i], this)) {
return true;
}
}
}));
}
for (i = 0; i < len; i++) {
jQuery.find(selector, self[i], ret);
}
// Needed because $( selector, context ) becomes $( context ).find( selector )
ret = this.pushStack(len > 1 ? jQuery.unique(ret) : ret);
ret.selector = this.selector ? this.selector + " " + selector : selector;
return ret;
},
filter: function (selector) {
return this.pushStack(winnow(this, selector || [], false));
}
});