`
ywxowen999
  • 浏览: 23853 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
社区版块
存档分类
最新评论

compareDocumentPosition与contains

阅读更多
研究KISSY 1.3RC源代码DOM/traversal 发现这样一段代码
        __contains =
            documentElement.compareDocumentPosition ?
                function (a, b) {
                    return !!(a.compareDocumentPosition(b) & 16);
                } :
                documentElement.contains ?
                    function (a, b) {
                        if (a.nodeType == NodeType.DOCUMENT_NODE) {
                            a = a.documentElement;
                        }
                        // !a.contains => a===document || text
                        // 注意原生 contains 判断时 a===b 也返回 true
                        b = b.parentNode;

                        if (a == b) {
                            return true;
                        }

                        // when b is document, a.contains(b) 不支持的接口 in ie
                        if (b && b.nodeType == NodeType.ELEMENT_NODE) {
                            return a.contains && a.contains(b);
                        } else {
                            return false;
                        }
                    } : 0;


这段代码的作用是判断一个节点是另一个节点的父节点。代码中主要用到了compareDocumentPosition与contains两个方法。
下面认识一下这两个方法。
contains是IE发明的函数,后来也有别的浏览器支持,比如Chrome,opera,有资料说firefox不支持此方法,但我用firefox15测试发现已经支持此方法。用法如下:
el.contains(el2);
如果 el包含el2 或 el === el2,返回true;否则返回false。

这很简单,接着说compareDocumentPosition
这个函数来自DOM Level 3 规范,标准浏览器都支持,但IE6-8不支持,IE从9开始支持。这个函数的返回值有点难理解,下面细说:

<div id="a">
    <div id="b"></div>
</div>
<script type="text/javascript">
   alert(a.compareDocumentPosition(b));
</script>


在Chrome试试这个例子,结果是 20。这里的 20 表示什么呢?下面先看一些常见的返回值:
  33 => 100001
  20 => 010100
  16 => 010000
  10 => 001010
    8 => 001000
    4 => 000100
    2 => 000010
    1 => 000001
    0 => 000000

很明显,例子的结果是第2个。要说明20的意义,需要先分析右边的二进制数。

这个二进制数分6位,从左到右依次是(如果符合条件,该位为1,否则为0):
  第1位:浏览器的私有使用
  第2位:a是b的祖先节点
  第3位:a是b的子孙节点
  第4位:a是b前面的节点
  第5位:a是b后面的节点
  第6位:a和b在不同的文档(或者一个在文档之外)

说到这里,20的意思就明显了,即 a是b的祖先节点,同时 a是b前面的节点。其实通常用到的是第2-5位,我觉得这四位已经足够表示任何位置关系了,也许你会问,a等于b 的情况怎么表示呢?
逆向思维一下,如果这四位都是0,也就是说,既不是父节点,又不是子节点,既不在前面,又不在后面,那唯一的解释就是a 等于 b,答案就是 000000。

知道了这些再来看代码 return !!(a.compareDocumentPosition(b) & 16);
为什么要&16? 我们知道16的2进制为10000 ,我们发现之后与左数第五位为1的数做&运算才会得到非零数,对非零做两次!操作就获得了一个布尔值。那么谜底解开了,这句的作用就是判断一个节点是否是另一个节点的祖先节点。
继续分析代码:
                        if (a.nodeType == NodeType.DOCUMENT_NODE) {
                            a = a.documentElement;
                        }
                        // !a.contains => a===document || text
 

这段代码考虑到了一种情况,就是当第一个参数是document的情况,document本身不是一个节点,所以contains方法无法对其进行比较,但是在逻辑上我们可以把document当成是最外层节点来处理,似乎更加合理。
                       // 注意原生 contains 判断时 a===b 也返回 true
                        b = b.parentNode;

                        if (a == b) {
                            return true;
                        }

contrains方法判断a与b对象的关系式还会将a 等于 b这种情况也返回true。上面这段代码将这种情况做了特殊处理。
最后一段代码就是使用contains方法来判断a与b的关系。

*注:在比较节点时有一种特殊情况,就是两个节点其中一个或两个还没有被放入DOM树中,这种情况下的比较结果结果在个浏览器中表现不一致,请使用者注意。
参考:
【1】http://www.cnblogs.com/zhujl/archive/2012/03/08/2384514.html
【2】http://www.codesky.net/article/201111/116405.html
END
分享到:
评论

相关推荐

    contains和compareDocumentPosition 方法来确定是否HTML节点间的关系

    `contains()` 和 `compareDocumentPosition()` 是JavaScript中用于解决这一问题的关键方法。本文将深入探讨这两个方法,以及它们在不同浏览器中的实现。 首先,`DOMElement.contains(DOMNode)` 方法主要用来检查一...

    javascript contains和compareDocumentPosition 方法来确定是否HTML节点间的关系

    在实际开发中,`contains()` 和 `compareDocumentPosition()` 方法能够帮助开发者高效地进行DOM操作和节点位置的判断。虽然在不同浏览器中的兼容性支持有所不同,通过合理使用polyfills和兼容性代码,可以确保这些...

    document.contains:用于`document.contains'的Polyfillshim

    因此,当`compareDocumentPosition`的结果与16进行按位与运算得到非零值时,说明节点B是节点A的后代。 `document.contains`的Polyfill在处理跨框架(iframe)或跨窗口的情况时尤其重要,因为它能正确处理这些复杂...

    js contains方法实现代码

    这里同样使用compareDocumentPosition方法,并检查结果是否与16按位与后非零。 通过上述方法,可以在不直接支持contains方法的浏览器中实现类似的功能。代码示例中还展示了如何使用这些方法进行测试,即创建父元素...

    跨浏览器的 mouseenter mouseleave 以及 compareDocumentPosition的使用说明

    在IE浏览器中,我们可以使用`parentNode.contains(childNode)`来判断childNode是否是parentNode的子节点,但这个方法在非IE浏览器中不通用。因此,对于跨浏览器的解决方案,我们可以使用`!!(node1....

    javascript中mouseover、mouseout使用详解

    3. 为了提高性能,可以使用compareDocumentPosition或contains方法来优化子元素与父元素之间的包含关系判断。这些方法可以避免遍历父元素带来的性能问题。使用这些DOM属性或方法可以快速判断一个元素是否为另一个...

    超级炫酷的效果js实现动画导航菜单

    contains(target,getEvent(e).relatedTarget||getEvent(e).fromElement) && !((getEvent(e).relatedTarget||getEvent(e).fromElement)===target); } else { return !contains(target,getEvent(e).relatedTarget||...

    javascript比较文档位置

    主要涉及两个方法:`contains()`和`compareDocumentPosition()`。 1、`DOMElement.contains(DOMNode)`: 这个方法最初由IE引入,用于判断一个DOM Node是否在另一个DOM Element内部。在优化CSS选择器遍历,如查找`#...

    JavaScript和JQuery的鼠标mouse事件冒泡处理

    `contains`方法在不同的浏览器中有不同的实现,例如在IE中是`contains`方法,而在Firefox中则是`compareDocumentPosition`方法。因此,在跨浏览器开发时可能需要相应的兼容性处理代码。 在JQuery中,事件处理与原生...

    比较文档位置

    一个很棒的 blog 文章,是 PPK 两年前写的,文章中解释了 contains() 和 compareDocumentPosition() 方法运行在他们各自的浏览器上。从那起,我已经对这些方法做了大量的研究,并且已经在很多场合使用他们。在很多...

    javascript 常用DomAPI总结

    #### 二、节点属性与方法 ##### 1. Node 节点属性 - **Node.nodeName**: 返回节点名称,只读。 - **Node.nodeType**: 返回节点类型的常数值,只读。 - **Node.nodeValue**: 返回 Text 或 Comment 节点的文本值,...

    jQuery中使用了document和window哪些属性和方法小结

    7. **document.documentElement.compareDocumentPosition()**:比较两个节点在文档中的相对位置,适用于非IE9以下的浏览器。 8. **document.documentElement.doScroll()**:这是一个IE特有的方法,用于模拟用户滚动...

    前端面试题目整理

    8. **Node.compareDocumentPosition(node)**: 返回一个 7 位的二进制值,表示参数节点和当前节点的关系。 9. **Node.isEqualNode(otherNode)**: 返回布尔值,用于检查两个节点是否相等。 10. **Node.normalize()**: ...

    jquery需要的所有js文件

    e++)a.options[d[e][0]]&&d[e][1].apply(a.element,c)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(b,c){if(a(b...

Global site tag (gtag.js) - Google Analytics