从右到左选择:五大迭代器
如果是从左到右,我们想过滤一些节点,就用现在手头上的节点就行了,但从右到左,我们就需要根据这些节点的父亲、孩子、兄弟进行过滤,而且过滤后,这些用作比较的节点不能丢弃掉,它们可以还要用于下一次的过滤。这样就存在一个代理关系,我们需要一些代理器来干这事情。当然像div.aaa是不需要代理器,但div div.aaa就需要了。在从左到右的情况下,我们所有说的关系选择器,主要有亲子兄长与相邻三种,遇到后代选择器,我们可以转化为通配符选择器与标签选择器。而在从右到左,关系选择器就包括后代通配符亲子兄长相邻五种,通配符实质是一种带层次关系的后代选择器。
//取得候选集的共同父节点的合集 var getParent = function (testee,result,yess,pid){ while ((testee = testee.parentNode)){ pid = testee.uniqueID || (testee.uniqueID = dom.UID++); if (yess[pid]){ result = testee } } return result; } var iterators = { current: function (nextset){ var set = this , nodes = this .nodes,tagName = this .tagName, filter = this .filter,args = this .args, result = [], testee, uid; for ( var i = 0,ri = 0, node;node = nodes[i++];){ uid = node.uniqueID || (node.uniqueID = dom.UID++); testee = set[uid] || node; if ((!tagName || tagName === testee.nodeName) && (!filter || filter.apply(testee,args))){ result[ri++] = node; nextset[uid] = testee; } } nextset.nodes = result; }, parent: function (nextset){ var set = this , nodes = this .nodes,tagName = this .tagName, filter = this .filter,args = this .args, result = [], yess = {}, testee, uid, pid; for ( var i = 0,ri = 0, node; node = nodes[i++];){ uid = node.uniqueID || (node.uniqueID = dom.UID++); testee = set[uid] || node; while ((testee = testee.parentNode) && testee.nodeType === 1 ){ pid = testee.uniqueID || (testee.uniqueID = dom.UID++); if (yess[pid]){ result[ri++] = node; nextset[uid] = testee; break ; } if ((!tagName || tagName === testee.nodeName) && (!filter || filter.apply(testee,args))){ yess[pid] = result[ri++] = node; nextset[uid] = testee; } break ; } } nextset.nodes = result; }, iterators.parents = function (nextset) { var set = this , nodes = this .nodes, tagName = this .tagName, filter = this .filter, args = this .args, level = this .level, _level, result = [], testee, uid, pid, yess = {}; for ( var i = 0, ri = 0, node; node = nodes[i++];) { uid = node.uniqueID || (node.uniqueID = dom.UID++); testee = set[uid] || node; while ((testee = testee.parentNode)) { if (testee.nodeType === 1) { if (level) { _level = level; while (_level-- && (testee = testee.parentNode)) { } if (!testee) { break ; } } pid = testee.uniqueID || (testee.uniqueID = dom.UID++); if (yess[pid]) { result[ri++] = node; nextset[uid] = nextset[yess[pid].uniqueID]; break ; } if ((!tagName || tagName === testee.nodeName) && (!filter || filter.apply(testee, args))) { yess[pid] = result[ri++] = node; nextset[uid] = getParent(testee, result, yess, pid); break ; } } } } nextset.nodes = result; } border: function (nextset){ var set = this , nodes = this .nodes,tagName = this .tagName, filter = this .filter,args = this .args, result = [], testee, uid; for ( var i = 0,ri = 0, node;node = nodes[i++];){ uid = node.uniqueID || (node.uniqueID = dom.UID++); testee = set[uid] || node; while ((testee = testee.previousSibling) && testee.nodeType === 1){ if ((!tagName || tagName === testee.nodeName) && (!filter || filter.apply(testee,args))){ result[ri++] = node; nextset[uid] = testee; } break ; } } nextset.nodes = result; }, borders: function (nextset){ var set = this , nodes = this .nodes,tagName = this .tagName, filter = this .filter,args = this .args, result = [], yess = {}, testee, uid, pid; for ( var i = 0,ri = 0, node;node = nodes[i++];){ uid = node.uniqueID || (node.uniqueID = dom.UID++); testee = set[uid] || node; while ((testee = testee.previousSibling) && testee.nodeType === 1){ pid = testee.uniqueID || (testee.uniqueID = dom.UID++); if (yess[pid]){ result[ri++] = node; nextset[uid] = testee break ; } if ((!tagName || tagName === testee.nodeName) && (!filter || filter.apply(testee,args))){ yess[pid] = result[ri++] = node; nextset[uid] = testee; break ; } } } nextset.nodes = result; } } |
它们几个好相似,正在考虑是否动态生成它们……
用时间截代替UID的筛选功能
选择div div div
<div class = "bbb" >3 <div class = "1" > <div class = "11" > </div> </div> <div class = "2" > </div> <div class = "3" > </div> </div> <div class = "aaa" >3 <div class = "4" > </div> <div class = "5" > </div> <div class = "6" > </div> </div> |
后代
var fathers = function () { var querytime = dom.querytime //new Date - 0 var nodes = this [0],set = this [1],args = this [4], filter = this [5],_set = [], _nodes = [], i = 0, ri = 0,node, testee; while ((testee = set[i])) { node = testee; //node至始自终从候选集中甄选,testee则从set的元素的长辈里甄选 while ((testee = testee.parentNode)) { if (testee.querytime === querytime) { _set[ri] = testee; _nodes[ri++] = nodes[i]; break ; } if (testee.nodeName === "DIV" ) { testee.querytime = querytime _set[ri] = testee; _nodes[ri++] = nodes[i]; break ; } } i++; } this [0] = _nodes; this [1] = _set; this .length = 3; } |
亲子
var father = function () { var querytime = dom.querytime; var nodes = this [0], set = this [1], args = this [4], filter = this [5], _set = [], _nodes = [], i = 0, ri = 0, node, testee; while ((testee = set[i])) { node = testee; while ((testee = testee.parentNode)) { if (testee.querytime === querytime) { _set[ri] = testee; _nodes[ri++] = node; break ; } if (testee.nodeName === "DIV" ) { testee.querytime = querytime _set[ri] = testee; _nodes[ri++] = node; } break ; } i++; } this [0] = _nodes; this [1] = _set; this .length = 3; } |
2011.1.26
var border = function (expr, set, flag_xml) { var selector, filter = Rage.filter; expr = expr.replace(reg_tag, function ($) { selector = $ === '*' ? true : flag_xm ? $ : $.toUpperCase(); return '' ; }); for ( var i = 0, n = set.length; i < n; i++) { if (testee = set[i]) { while ((testee = testee.previousSibling) && testee.nodeType !== 1) {}; testee = testee && testee.nodeName === selector && testee || false ; } } expr && filter.call( null , expr, set, true ); } |
var parent = function (expr, set, flag_xml) { var selector, filter = Rage.filter; expr = expr.replace(reg_tag, function ($) { selector = $ === '*' ? true : flag_xm ? $ : $.toUpperCase(); return '' ; }); for ( var i = 0, n = set.length; i < n; i++) { if (testee = set[i]) { testee = testee.parentNode; testee = testee && testee.nodeName === selector && testee || false ; } } expr && filter.call( null , expr, set, true ); } |
var borders = function (expr, set, flag_xml) { var selector, filter = Rage.filter,_filter = Rage._filter,flag_fn = false ,old = expr,prop = 'previousSibling' ; expr = expr.replace(reg_first, function ($) { if (reg_tag.test($)) { selector = $ === '*' ? true : flag_xm ? $ : $.toUpperCase(); } else { selector = $; flag_fn = true ; } return '' ; }); if (expr === old) { throw old + '存在语法错误' ; } _filter.call( null , selector, set, prop, flag_fn); expr && filter.call( null , expr, set, true ); } |
var parents = function (expr, set, flag_xml) { var selector, filter = Rage.filter,_filter = Rage._filter, flag_fn = false ,old = expr, prop = 'parentNode' ; expr = expr.replace(reg_first, function ($) { if (reg_tag.test($)) { selector = $ === '*' ? true : flag_xm ? $ : $.toUpperCase(); } else { selector = $; flag_fn = true ; } return '' ; }); if (expr === old) { throw old + '存在语法错误' ; } _filter.call( null , selector, set, prop, flag_fn); expr && filter.call( null , expr, set, true ); } |
如果您觉得此文有帮助,可以打赏点钱给我支付宝1669866773@qq.com ,或扫描二维码


机器瞎学/数据掩埋/模式混淆/人工智障/深度遗忘/神经掉线/计算机幻觉/专注单身二十五年
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义