首页 > 编程语言 >深入学习jquery源码之filter()与find()

深入学习jquery源码之filter()与find()

时间:2023-02-23 22:03:02浏览次数:39  
标签:jquery jQuery return whitespace function elem filter 源码 context


深入学习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类的元素

<p>Hello</p><p>Hello Again</p><p class="selected">And Again</p>
$("p").filter(".selected")
[ <p class="selected">And Again</p> ]

保留第一个以及带有select类的元素

<p>Hello</p><p>Hello Again</p><p class="selected">And Again</p>
$("p").filter(".selected, :first")
[ <p>Hello</p>, <p class="selected">And Again</p> ]

保留子元素中不含有ol的元素。

<p><ol><li>Hello</li></ol></p><p>How are you?</p>
$("p").filter(function(index) {
return $("ol", this).length == 0;
});
[ <p>How are you?</p> ]

find(expr|obj|ele)

概述

搜索所有与指定表达式匹配的元素。这个函数是找出正在处理的元素的后代元素的好方法。

所有搜索都依靠jQuery表达式来完成。这个表达式可以使用CSS1-3的选择器语法来写。

参数

expr String 

用于查找的表达式

jQuery object object

一个用于匹配元素的jQuery对象

element DOMElement

一个DOM元素

从所有的段落开始,进一步搜索下面的span元素。与$("p span")相同。

<p><span>Hello</span>, how are you?</p>
$("p").find("span")
[ <span>Hello</span> ]

 

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 << 31,

// Instance methods
hasOwn = ({}).hasOwnProperty,
arr = [],
pop = arr.pop,
push_native = arr.push,
push = arr.push,
slice = arr.slice,
// Use a stripped-down indexOf as it's faster than native
// http://jsperf.com/thor-indexof-vs-for/5
indexOf = function (list, elem) {
var i = 0,
len = list.length;
for (; i < len; i++) {
if (list[i] === elem) {
return i;
}
}
return -1;
},

booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",

// Regular expressions

// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
whitespace = "[\\x20\\t\\r\\n\\f]",
// http://www.w3.org/TR/css3-syntax/#characters
characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",

// Loosely modeled on CSS identifier characters
// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
identifier = characterEncoding.replace("w", "w#"),

// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
// Operator (capture 2)
"*([*^$|!~]?=)" + whitespace +
// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
"*\\]",

pseudos = ":(" + characterEncoding + ")(?:\\((" +
// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
// 1. quoted (capture 3; capture 4 or capture 5)
"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
// 2. simple (capture 6)
"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
// 3. anything else (capture 2)
".*" +
")\\)|)",

// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
rwhitespace = new RegExp(whitespace + "+", "g"),
rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"),

rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"),
rcombinators = new RegExp("^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"),

rattributeQuotes = new RegExp("=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g"),

rpseudo = new RegExp(pseudos),
ridentifier = new RegExp("^" + identifier + "$"),

matchExpr = {
"ID": new RegExp("^#(" + characterEncoding + ")"),
"CLASS": new RegExp("^\\.(" + characterEncoding + ")"),
"TAG": new RegExp("^(" + characterEncoding.replace("w", "w*") + ")"),
"ATTR": new RegExp("^" + attributes),
"PSEUDO": new RegExp("^" + pseudos),
"CHILD": new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
"*(\\d+)|))" + whitespace + "*\\)|)", "i"),
"bool": new RegExp("^(?:" + booleans + ")$", "i"),
// For use in libraries implementing .is()
// We use this for POS matching in `select`
"needsContext": new RegExp("^" + whitespace + "*[>+~]|:(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<24
// Workaround erroneous numeric interpretation of +"0x"
return high !== high || escapedWhitespace ?
escaped :
high < 0 ?
// BMP codepoint
String.fromCharCode(high + 0x10000) :
// Supplemental Plane codepoint (surrogate pair)
String.fromCharCode(high >> 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<4.0
// Detect silently failing push.apply
arr[preferredDoc.childNodes.length].nodeType;
} catch (e) {
push = {
apply: arr.length ?

// Leverage slice if possible
function (target, els) {
push_native.apply(target, slice.call(els));
} :

// Support: IE<9
// Otherwise append directly
function (target, els) {
var j = target.length,
i = 0;
// Can't trust NodeList.length
while ((target[j++] = els[i++])) { }
target.length = j - 1;
}
};
}

function Sizzle(selector, context, results, seed) {
var match, elem, m, nodeType,
// QSA vars
i, groups, old, nid, newContext, newSelector;

if ((context ? context.ownerDocument || context : preferredDoc) !== document) {
setDocument(context);
}

context = context || document;
results = results || [];
nodeType = context.nodeType;

if (typeof selector !== "string" || !selector ||
nodeType !== 1 && nodeType !== 9 && nodeType !== 11) {

return results;
}

if (!seed && documentIsHTML) {

// Try to shortcut find operations when possible (e.g., not under DocumentFragment)
if (nodeType !== 11 && (match = rquickExpr.exec(selector))) {
// Speed-up: Sizzle("#ID")
if ((m = match[1])) {
if (nodeType === 9) {
elem = context.getElementById(m);
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document (jQuery #6963)
if (elem && elem.parentNode) {
// Handle the case where IE, Opera, and Webkit return items
// by name instead of ID
if (elem.id === m) {
results.push(elem);
return results;
}
} else {
return results;
}
} else {
// Context is not a document
if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) &&
contains(context, elem) && elem.id === m) {
results.push(elem);
return results;
}
}

// Speed-up: Sizzle("TAG")
} else if (match[2]) {
push.apply(results, context.getElementsByTagName(selector));
return results;

// Speed-up: Sizzle(".CLASS")
} else if ((m = match[3]) && support.getElementsByClassName) {
push.apply(results, context.getElementsByClassName(m));
return results;
}
}

// QSA path
if (support.qsa && (!rbuggyQSA || !rbuggyQSA.test(selector))) {
nid = old = expando;
newContext = context;
newSelector = nodeType !== 1 && selector;

// qSA works strangely on Element-rooted queries
// We can work around this by specifying an extra ID on the root
// and working up from there (Thanks to Andrew Dupont for the technique)
// IE 8 doesn't work on object elements
if (nodeType === 1 && context.nodeName.toLowerCase() !== "object") {
groups = tokenize(selector);

if ((old = context.getAttribute("id"))) {
nid = old.replace(rescape, "\\$&");
} else {
context.setAttribute("id", nid);
}
nid = "[id='" + nid + "'] ";

i = groups.length;
while (i--) {
groups[i] = nid + toSelector(groups[i]);
}
newContext = rsibling.test(selector) && testContext(context.parentNode) || context;
newSelector = groups.join(",");
}

if (newSelector) {
try {
push.apply(results,
newContext.querySelectorAll(newSelector)
);
return results;
} catch (qsaError) {
} finally {
if (!old) {
context.removeAttribute("id");
}
}
}
}
}

// All others
return select(selector.replace(rtrim, "$1"), context, results, seed);
}

/**
* Create key-value caches of limited size
* @returns {Function(string, Object)} Returns the Object data after storing it on itself with
* property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
* deleting the oldest entry
*/
function createCache() {
var keys = [];

function cache(key, value) {
// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
if (keys.push(key + " ") > Expr.cacheLength) {
// Only keep the most recent entries
delete cache[keys.shift()];
}
return (cache[key + " "] = value);
}
return cache;
}

Sizzle.matches = function (expr, elements) {
return Sizzle(expr, null, null, elements);
};

Sizzle.matchesSelector = function (elem, expr) {
// Set document vars if needed
if ((elem.ownerDocument || elem) !== document) {
setDocument(elem);
}

// Make sure that attribute selectors are quoted
expr = expr.replace(rattributeQuotes, "='$1']");

if (support.matchesSelector && documentIsHTML &&
(!rbuggyMatches || !rbuggyMatches.test(expr)) &&
(!rbuggyQSA || !rbuggyQSA.test(expr))) {

try {
var ret = matches.call(elem, expr);

// IE 9's matchesSelector returns false on disconnected nodes
if (ret || support.disconnectedMatch ||
// As well, disconnected nodes are said to be in a document
// fragment in IE 9
elem.document && elem.document.nodeType !== 11) {
return ret;
}
} catch (e) { }
}

return Sizzle(expr, document, null, [elem]).length > 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));
}
});

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:jquery,jQuery,return,whitespace,function,elem,filter,源码,context
From: https://blog.51cto.com/u_11837698/6081940

相关文章

  • 深入学习jquery源码之prop()与removeProp()
    深入学习jquery源码之prop()与removeProp()prop(name|properties|key,value|fn)概述获取在匹配的元素集中的第一个元素的属性值。随着一些内置属性的DOM元素或window对象,如......
  • 深入学习jquery源码之addClass()和toggleClass()与hasClass()
    深入学习jquery源码之addClass()和toggleClass()与hasClass()addClass(class|fn)概述为每个匹配的元素添加指定的类名。参数class String一个或多个要添加到元素中的CSS类......
  • 深入学习jquery源码之siblings()和children()与contents()
    深入学习jquery源码之siblings()和children()与contents()siblings([expr])概述取得一个包含匹配的元素集合中每一个元素的所有唯一同辈元素的元素集合。可以用可选的表达式......
  • 深入学习jquery源码之jQuery中高质量的代码
    深入学习jquery源码之jQuery中高质量的代码1、this指向的问题 functionStudent(name,age,grade,school){Person.apply(this,arguments);}他就具备了Pe......
  • 深入学习jquery源码之next()和nextAll()与nextUntil()
    深入学习jquery源码之next()和nextAll()与nextUntil()next([expr])概述取得一个包含匹配的元素集合中每一个元素紧邻的后面同辈元素的元素集合。这个函数只返回后面那个紧邻......
  • 深入学习java源码之Math.sin()与 Math.sqrt()
    深入学习java源码之Math.sin()与Math.sqrt()native关键字凡是一种语言,都希望是纯。比如解决某一个方案都喜欢就单单这个语言来写即可。Java平台有个用户和本地C代码进行互......
  • 深入学习jquery源码之parent()和parents()与parentsUntil()
    深入学习jquery源码之parent()和parents()与parentsUntil()parent([expr])概述取得一个包含着所有匹配元素的唯一父元素的元素集合。你可以使用可选的表达式来筛选。参数exp......
  • 深入学习jquery源码之prev()和prevAll()与prevUntil()
    深入学习jquery源码之prev()和prevAll()与prevUntil()prev([expr])概述取得一个包含匹配的元素集合中每一个元素紧邻的前一个同辈元素的元素集合。可以用一个可选的表达式进......
  • slate源码解析(一)- 序言
    笔者从大学时期就开始接触的前端,在刚去实习的时候就被导师安排去做内网的一个小富文本工具。之后从毕业后干的第一份工作游戏客户端,到现在做着可视化相关的前端工作,都有在......
  • Java集合Set接口详解——含源码分析
    前言前几天我们看了​​Java集合List接口详解——含源码分析​​,今天我们看一个数据一个数据存储的另一个接口——Set。Set前面我们说List最大的特点是:​​有序,不唯一​​,而......