先声明一下DOM2中NodeIterator和TreeWalker这两类型真的只是用来玩玩的,因为性能不行遍历起来超级慢,在JS中基本用不到它们,除了《高程》上有两三页对它的讲解外,谷歌的学习资料也是甚少(倒是有挺多国外文章)...由于本着不放过任何知识的态度,结合着自己的理解学习了下这两玩意,你们对这两东西了解了解就好~

DOM2级遍历和范围模块定义了两个用于完成顺序遍历DOM结构的类型:NodeIterator和TreeWalker。这两类型基于给定起点对DOM结构执行深度优先先序遍历,兼容性>IE8和高版本其他浏览器可访问。

NodeIterator:

使用document.createNodeIterator(root, whatShow, filter, entityReferenceExpansion)创建NoedIterator类型实例iterator,所以原型链关系为:
iterator.__proto__->NodeIterator.prototype->Object.prototye

TreeWalker:

使用document.createTreeWalker(root, whatShow, filter, entityReferenceExpansion)创建TreeWalker类型实例walker,所以原型链关系为:
walker.__proto__->TreeWalker.prototype->Object.prototype

对比下来,其实就两个方法常用,nextNode()和previousNode()。TreeWalker.prototype比NodeIterator.prototype多了一些在不同方向上遍历的方法也就没什么了。
(1).在每个iterator中有一个内部指针指向根节点,nextNode方法是返回遍历器内部指针所在节点,然后会将指针移向下一个节点。previousNode()方法是先将指针移向上一个节点,然后返回该节点。所以nextNode()==previousNode()

(2).在每个walker中也有一个内部指针,但是指向根节点的第一个子节点,nextNode方法是返回遍历器所在节点然后并不移动指针(就是说指针和节点在同一处),previous()方法是先将指针移向上一个节点,然后返回该节点,所以这里nextNode() != previous()

所以TreeWalker.prototype就有一个currentNode属性,表示在上一次遍历中返回的节点:

(3).区别说完,说说它两的参数都是相同的:
root:想要作为搜索起点的树中的节点
whatToShow:表示要访问哪些节点的数字代码,来自NodeFilter.prototype还是NodeFilter自身上中的这些大写常量...

filter:是NodeFilter类型实例对象,或者是一个表示应该接受还是拒绝某种特定节点的函数。作用是当调用nextNode或previousNode时候要经过这个过滤器来删选想要的节点,如果说文档中任何一个节点走一步,那么根据筛选节点类型不同每次返回的节点实际上可能走了好几步。
entityReferenceExpansion:表示是否要扩展实体引用,false就好。

对了,NodeIterator和TreeWalker还有一点区别就是在使用NodeIterator对象时,NodeFilter.FILTER_SKIP和NodeFilter.FILTER_REJECT作用相同跳过指定节点。在使用TreeWalker对象时,NodeFilter.FILTER_SKIP会跳过相应节点继续前进到子树中下一个节点,NodeFilter.FILTER_REJECT会相应节点及该节点的整个子树。

OK!说完了上面的,也不知道大家有没有懂~不懂没关系反正这两类型也不常用,效率也差~
通过DOM遍历的这两类型很容易让人想到我们常用的document.getElementById,document.getElementsByTagName,document.getElementsByNames...系列方法不是也是在DOM中搜寻指定节点的么...这里用NodeIterator来实现一下

Document.prototype.getElementById = function(id){
var filter = function(node){
return node.id == id ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
}
var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, filter, false);
var node = iterator.nextNode();
return node;
} Document.prototype.getElementsByTagName = function(tagname){
var filter = function(node){
return node.tagName.toLowerCase() == tagname ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
}
var htmlcollection = [];
var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, filter, false);
var node = iterator.nextNode();
while(node!=null){
htmlcollection.push(node);
node = iterator.nextNode();
}
htmlcollection.__proto__ = HTMLCollection.prototype;
return htmlcollection;
}


成功!其他的方法类似的,感兴趣可以自行实现~

stackoverflow里有人提出了When to use NodeIterator? 把querySelector和filter过滤进行比较,这谁快谁慢光看名字就显而易见嘛,感兴趣可以看看啊~我粗略测试下

也不知道人家JS引擎中getElementById真正是怎么实现的,改天抽空看看~

参考

《JavaScript高级程序设计》

JavaScript标准参考教程-document节点

玩转DOM遍历——用NodeIterator实现getElementById,getElementsByTagName方法的更多相关文章

  1. DOM遍历

    前面的话 DOM遍历模块定义了用于辅助完成顺序遍历DOM结构的类型:Nodeiterator和TreeWalker,它们能够基于给定的起点对DOM结构执行深度优先(depth-first)的遍历操作. ...

  2. JQuery总结:选择器归纳、DOM遍历和事件处理、DOM完全操作和动画 (转)

    JQuery总结:选择器归纳.DOM遍历和事件处理.DOM完全操作和动画 转至元数据结尾 我们后台可能用到的页面一般都是用jquery取值赋值的,发现一片不错的文章 目录 JQuery总结一:选择器归 ...

  3. jQuery 源码分析(十九) DOM遍历模块详解

    jQuery的DOM遍历模块对DOM模型的原生属性parentNode.childNodes.firstChild.lastChild.previousSibling.nextSibling进行了封装 ...

  4. getElementById() getElementsByTagName() getElementsByClassName() querySlector() querySlectorAll()区别

    1. getElementById() getElementsByTagName()  javascript原生的方法,这两个不会有兼容性问题. 2. getElementsByClassName() ...

  5. [DOM Event Learning] Section 1 DOM Event 处理器绑定的几种方法

    [DOM Event Learning] Section 1 DOM Event处理器绑定的几种方法   网页中经常需要处理各种事件,通常的做法是绑定listener对事件进行监听,当事件发生后进行一 ...

  6. Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解

    Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解 一.Jquery遍历筛选数组 1.jquery grep()筛选遍历数组 $().ready( function(){ v ...

  7. JQuery遍历json数组的3种方法

    这篇文章主要介绍了JQuery遍历json数组的3种方法,本文分别给出了使用each.for遍历json的方法,其中for又分成两种形式,需要的朋友可以参考下 一.使用each遍历 $(functio ...

  8. Java遍历List集合的三种方法

    Java遍历List集合的三种方法 List<String> list = new ArrayList<String>(); list.add("aaa") ...

  9. (转载)Java中如何遍历Map对象的4种方法

    在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...

随机推荐

  1. OSX活动监视器关闭spotlight 、mds_stores等进程

    如果是机械盘,spotlight .mds_stores严重影响使用体验 今天早上一开机,设备速度慢的受不了,随便打开一个应用都几分钟.通过top查看,CPU剩余90%以上.所以并不是CPU不足导致. ...

  2. 点击edittext并显示其内容

    package com.example.sum;//sum import com.example.sum.R;//sum import android.app.Activity; import and ...

  3. @Bean 小知识

    先说结论 @Bean 可以用在任意方法上. -- 也可以用在注解上面. @Bean 仅在Spring创建bean时起作用. 这应该算一个小技巧,在一个平常类(非@Configuration class ...

  4. 工具类之Mutex

    Mutex在Android4.4的源代码包的./system/core/include/utils/Mutex.h中定义并且实现. 我们先复习一下Mutex在Linux中功能: Mutex出生的意义就 ...

  5. Hive:数据仓库工具,由Facebook贡献。

    Hadoop Common: 在0.20及以前的版本中,包含HDFS.MapReduce和其他项目公共内容,从0.21开始HDFS和MapReduce被分离为独立的子项目,其余内容为Hadoop Co ...

  6. c#并行扫描端口控制台程序

    static void Main(string[] args) { Console.WriteLine("请输入ip"); string ip = Console.ReadLine ...

  7. 滚动到指定位置js

    function mScroll(id){ $("html,body").stop(true); $(); }

  8. Hibernate_day02--Hibernate的一级缓存

    Hibernate的一级缓存 什么是缓存 1 数据存到数据库里面,数据库本身是文件系统,使用流方式操作文件效率不是很高. (1)把数据存到内存里面,不需要使用流方式,可以直接读取内存中数据 (2)把数 ...

  9. git练习

    git commit 提交记录 git branch <branch_name> 建立名为branch_name的分支 git checkout <name>:git comm ...

  10. Java使用Apache POI进行Excel导入和导出

    Manve依赖 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --> <dependency> ...