在学习“contains()和compareDocumentPositon()"过程中遇到的一点疑惑!

JS开发人员经常都需要确定某个节点是否包含另一个节点,由此IE率先引入了contains()函数,随后,Safari3及其更高版本,Opera 8及其更高版本,Chrome都支持了这个方法(Safari 2.x中虽然也支持这个方法,但无法正常使用)。FireFox不支持这个方法,但在DOM3中提供了一个替代方法compareDocuemntPosition()。由于此种原因,要想跨平台确定某个节点是否包含另一个节点,就必须提供一个通用的contains()函数来解决这种差异,通常的解法方法如下:

  var Contains = function(a, b){
     return a.contains ? a != b && a.contains(b) : !!(a.compareDocumentPosition(b) & 16);
}

以上代码中,通过三目运算符确定浏览器是否支持contains()方法,如果支持该方法,则对a != b && a.contains(b)进行判断,并返回一个布林值,否则对

!!(a.compareDocumentPosition(b) & 16)进行判断,我的疑惑正在于此,我们知道,逻辑非操作符由一个叹号(!)表示,可以用于ECMAscript中的任何值,无论这个值是什么数据类型,这个操作符都会返回一个布尔值。同时使用两个逻辑非(!)操作符,就会模拟Boolean()转型函数的行为,于是就得到了这个值真正对应的布尔值。也就是说实际判断的是a.compareDocumentPosition(b) & 16。在使用compareDocumentPosiotn()方法时会返回一个表示该关系的位掩码,下表列出了这个位掩码的可能值:

掩码 节点关系
1 无关(给定的节点不在当前文档中)
2 居前(给点的节点在DOM树种位于给点的节点之前)
4 居后(给点的节点在DOM树种位于给点的节点之后)
8 包含(给定的节点是参考节点的祖先)
16 被包含(给定的节点是参考节点的后代)

为模仿contanins(),应该关注的是16。如果a.compareDocumentPosition(b)得出的值是1,2,4,8,16,那么!!(1&16),!!(2&16),!!(4&16)... ...怎么确认呢?讲到这里我们必须注意”&“操作符,它叫作”按位与“,从本质上讲,按位与就是将两个数值的每一位对齐,然后根据下表中的规则,对相同位置上的两个数进行操作:

第一个数值的位 第二个数值的位 结果
1 1 1
1 0 0
0 1 0
0 0 0

以16&16为例,先将16转换为二进制数,16=0000 0000 0000 0000 0000 0000 0001 0000,那么16&16=0000 0000 0000 0000 0000 0000 0001 0000(具体操作过程可参考位操作符的原则),那么!!(16&16)=true(对于其它几个掩码,大家不妨也试一下,其与16进行按位与操作的结果都是0)。因此通过以上方法,便能通过!!(a.compareDocumentPosition(b) & 16)模拟出a.contanins(b)。

时间: 2024-10-22 22:41:54

在学习“contains()和compareDocumentPositon()"过程中遇到的一点疑惑!的相关文章

在学习"$(this)和this"过程中遇到的一点疑惑!

在学习JQuery的过程中,我遇到了$(this),this,通过查阅网上资料,我发现大部分来源中对于它们的解释基本一致,其最终来源似乎都来自一位叫做Remy Sharp的程序员的一篇文章https://remysharp.com/2007/04/12/jquerys-this-demystified ,其中我发现了一些解释并不够清楚的地方,写下来与各位讨论. 以下是在查阅资料过程过发现的一个例子: $("#desktop a img").each(function(index){ a

关于学习C#泛型委托过程中发现的一些疑惑,大家一起讨论下

大家知道泛型委托Action,是定义一个没有返回值的委托. 例如: public Action<int, int> AddAction = (x, y) => { Console.WriteLine(x+y); }; 定义一个Action 可以在Action上F12进入可以看到源码为: public delegate void Action<T1, T2>(T1 arg1, T2 arg2); 这里发现一个问题,T1,T2是什么类型呢,在哪里定义的,我按F12并没有找到对应的

Ubuntu14.04安装mysql及过程中遇到的一点小问题

Ubuntu14.04出来有段时间了,前几天刚升级到这个版本,新鲜了一把.不过安装mysql时遇到了一点小问题,记录一下以备后用. 预备操作: 网上安装mysql的方法不少,大体有这么三种. 1. 从网上安装 sudo apt-get install mysql-server.装完已经自动配置好环境变量,可以直接使用mysql的命令. 2. 安装离线包,以mysql-5.0.45-linux-i686-icc-glibc23.tar.gz为例. 3. 二进制包安装:安装完成已经自动配置好环境变量

Hadoop学习1--解决启动过程中的问题

http://www.cnblogs.com/kinglau/p/3270160.html $ bin/start-all.sh-bash: bin/start-all.sh: No such file or directory 解决历程: 1.一堆人说是没权限,把当前登陆用户对Hadoop文件夹的权限,设置为完全控制. 结果:不起作用

C++中map的一点疑惑...

int CRuntimePara::getInt(const string& strKey,int iDefault){ map<string,string>::const_iterator iter; if ((iter = _mapParaValue.find(strKey)) != _mapParaValue.end()) return atoi((*iter).second.c_str()); else return iDefault;} _mapParaValue.end()

学习webpack3.x过程中遇到的问题

这篇博客主要记录的是本人在学习webpack3.x的过程中遇到的问题(虽然这几天4.0刚出来,但是我还是先学一下3.x吧) 1.配置文件可以用webpack启服务和热更新,步骤如下: ① 先下载:webpack-dev-server cnpm install webpack-dev-server --save-dev ② 配置webpack.config.js module.exports = { // 配置入口文件 entry:{}, // 配置出口文件 output:{}, // 配置模块:

Java泛型学习笔记 - (七)浅析泛型中通配符的使用

一.基本概念:在学习Java泛型的过程中, 通配符是较难理解的一部分. 主要有以下三类:1. 无边界的通配符(Unbounded Wildcards), 就是<?>, 比如List<?>. 无边界的通配符的主要作用就是让泛型能够接受未知类型的数据. 2. 固定上边界的通配符(Upper Bounded Wildcards): 使用固定上边界的通配符的泛型, 就能够接受指定类及其子类类型的数据. 要声明使用该类通配符, 采用<? extends E>的形式, 这里的E就是

学习Hadoop过程中遇到的困难

1:Shuffle Error: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out 这是reduce预处理阶段shuffle时获取已完成的map的输出失败次数超过上限造成的,上限默认为5.引起此问题的方式可能会有很多种,比如网络连接不正常,连接超时,带宽较差以及端口阻塞等,通常框架内网络情况较好是不会出现此错误的. 2:Too many fetch-failures Answer: 出现这个问题主要是结点间的连通不够全面. 1) 检查 ./etc/h

个人学习C++过程中对const的总结:初始化系列之用字面值常量与其他类型的值初始化的区别(一)

const这个系列博大精深,在学习过程一点一点积累记录.但是由于随笔在发布之后不能修改,有了新的想法之后不能再在原随笔上修改,只好用一个个系列来慢慢积累. 哈哈,在发布之后发现是可以继续编辑的,好吧,不管了,这种方式挺好. 正文: 昨晚接触到一个算法题目,回文字符串,在网上找了某段代码,但是发现有点问题,原形大概如下: .... const int len=mystr.size(); //mystr是string的一个实例,其实我挺奇怪这里为什么用int而不是string::size_type或