读jquery-3.2.1源码 涉及到js基础知识汇总
选择器matches querySelector querySelectorAll
compareDocumentPosition
contains
nodeType
array shift unshift push pop
一、matches
参考文章:
https://www.lyblog.net/detail/601.html
JavaScript中matches(matchesSelector)的兼容写法
在SELECTORS API Level 2规范中,为DOM节点添加了一个方法,主要是用来判断当前DOM节点不否能完全匹配对应的CSS选择器规则;如果匹配成功,返回true,反之则返回false。
语法如下:
element.matches(String selector);
这个方法在我们做事件委托时就显得非常有用,示例代码如下:
document.querySelector('#wrap').addEventListener('click',function(e){
if(e.target.matches('a.btn')) {
e.preventDefault();
//TODO something
}
},false);
对应的HTML代码如下:
<div id="wrap">
<a class="btn" href="http://www.lyblog.net">点击代码</a>
<span class="btn">不可点击按钮</span>
</div>
对于以上,jq的一种写法可以如下:
$('#wrap').delegate('a.btn','click',function(e){
//TODO something
});
实际情况下,’matches’支持情况也不太尽人意,你可以到 caniuse 查看参考结果。但几乎所有的现代浏览器实验性的实现了这个方法(如:chrome中以webkitMatchesSelector,firefox中以mozMatchesSelector,IE 9+中则以msMatchesSelector替代)。
我们知道,jq中内置了js实现的css选择器sizzle,而sizzle中也是提供了类似功能的API接口,调用如下:
Sizzle.matchesSelector( DOMElement element, String selector );
通常在开发阶段兼容IE 8+及移动端,我更偏向于脱离jq等重量级的库。所以有了以下的兼容写法:
function matchesSelector(element, selector){
if(element.matches){
return element.matches(selector);
} else if(element.matchesSelector){
return element.matchesSelector(selector);
} else if(element.webkitMatchesSelector){
return element.webkitMatchesSelector(selector);
} else if(element.msMatchesSelector){
return element.msMatchesSelector(selector);
} else if(element.mozMatchesSelector){
return element.mozMatchesSelector(selector);
} else if(element.oMatchesSelector){
return element.oMatchesSelector(selector);
}
}
但主要IE 8正好不支持msMatchesSelector方法,可以用如下方法处理以上函数,以便支持IE 8,完善之后的代码如下:
function matchesSelector(element,selector){
if(element.matches){
return element.matches(selector);
} else if(element.matchesSelector){
return element.matchesSelector(selector);
} else if(element.webkitMatchesSelector){
return element.webkitMatchesSelector(selector);
} else if(element.msMatchesSelector){
return element.msMatchesSelector(selector);
} else if(element.mozMatchesSelector){
return element.mozMatchesSelector(selector);
} else if(element.oMatchesSelector){
return element.oMatchesSelector(selector);
} else if(element.querySelectorAll){
var matches = (element.document || element.ownerDocument).querySelectorAll(selector),
i = 0;
while(matches[i] && matches[i] !== element) i++;
return matches[i] ? true: false;
}
throw new Error('Your browser version is too old,please upgrade your browser');
}
由于querySelectorAll是SELECTORS API Level 1中提出来的,所以在浏览器中的表现的比较不错。所以以上的解决方案可以在不考虑IE 7-以下浏览器的情况下使用。
二、querySelector
http://www.cnblogs.com/daxian2012/archive/2012/10/18/2729359.html
querySelector 和 querySelectorAll 方法是 W3C Selectors API 规范中定义的。他们的作用是根据 CSS 选择器规范,便捷定位文档中指定元素。
目前几乎主流浏览器均支持了他们。包括 IE8(含) 以上版本、 Firefox、 Chrome、Safari、Opera。
querySelector 和 querySelectorAll 在规范中定义了如下接口:
module dom { [Supplemental, NoInterfaceObject] interface NodeSelector { Element querySelector(in DOMString selectors); NodeList querySelectorAll(in DOMString selectors); }; Document implements NodeSelector; DocumentFragment implements NodeSelector; Element implements NodeSelector; };
从接口定义可以看到Document、DocumentFragment、Element都实现了NodeSelector接口。即这三种类型的元素都拥有者两个方法。querySelector和querySelectorAll的参数须是符合 css selector 的字符串。不同的是querySelector返回的是一个对象,querySelectorAll返回的一个集合(NodeList)。
获取页面I属性D为test的元素:
1. document.getElementById("test");
2. //or
3. document.querySelector("#test");
4. document.querySelectorAll("#test")[0];
获取页面class属性为”red”的元素:
1. document.getElementsByClassName('red')
2. //or
3. document.querySelector('.red')
4. //or
5. document.querySelectorAll('.red')
Element.querySelector和Element.querySelectorAll和jQuery(element).find(selector)选择器的区别:
1. <divid="test1"><ahref="http://www.hujuntao.com/">设计蜂巢</a></div>
2. <pid="bar">111</p>
3. <script>
4. var d1 = document.getElementById('test1'),
5. obj1 = d1.querySelector('div a'),
6. obj2 = d1.querySelectorAll('div a');
7. obj3 = $(d1).find('div a');
8. console.log(obj1)//<a href="http://www.hujuntao.com/">设计蜂巢</a>
9. console.log(obj2.length)//1
10. console.log(obj3)//null
11. </script>
querySelectorAll 在文档内找全部符合选择器描述的节点包括Element本身
jQuery(element).find(selector) 在文档内找全部符合选择器描述的节点不包括Element本身
三.compareDocumentPosition 与 contains
http://www.cnblogs.com/pigtail/archive/2012/06/07/2540246.html
这两天在看Cloudgamer的js工具库 cloudgamer Js Library v0.1 ,里面有一个dom的contain方法,如下:
var D={
// 参见 JS从样式表取值的函数 currentStyle(IE),defaultView(FF)
contains: document.defaultView
? function (a, b) { return !!( a.compareDocumentPosition(b) & 16 ); }
: function (a, b) { return a != b && a.contains(b); }
}
我对compareDocumentPosition这个函数实在是陌生,见都没有见过,就上网找了一下,还真不错,找到了,扩展知识,做个记录吧……
1、DOMElement.contains(DOMNode)
这个方法起先用在 IE ,用来确定 DOM Node 是否包含在另一个 DOM Element 中。
当尝试优化 CSS 选择器遍历(像:“#id1 #id2”),这个方法很有用。你可以通过 getElementById 得到元素,然后使用 .contains() 确定 #id1 实际上是否包含 #id2。
注意:如果 DOMNode 和 DOMElement 相一致,.contains() 将返回 true ,虽然,一个元素不能包含自己。
2、NodeA.compareDocumentPosition(NodeB)
这个方法是 DOM Level 3 specification 的一部分,允许你确定 2 个 DOM Node 之间的相互位置。这个方法比 .contains() 强大。这个方法的一个可能应用是排序 DOM Node 成一个详细精确的顺序。
使用这个方法你可以确定关于一个元素位置的一连串的信息。所有的这些信息将返回一个比特码(Bit,比特,亦称二进制位)。
对于那些,人们知之甚少。比特码是将多重数据存储为一个简单的数字(译者注:0 或 1)。你最终打开 / 关闭个别数目(译者注:打开/关闭对应 0 /1),将给你一个最终的结果。
这里是从 NodeA.compareDocumentPosition(NodeB) 返回的结果,包含你可以得到的信息。
Bits Number Meaning
000000 0 元素一致
000001 1 节点在不同的文档(或者一个在文档之外)
000010 2 节点 B 在节点 A 之前
000100 4 节点 A 在节点 B 之前
001000 8 节点 B 包含节点 A
010000 16 节点 A 包含节点 B
100000 32 浏览器的私有使用
这个表格的意思如下:
满足a在b之前,而且a包含b,则返回结果就是4+16=20,则cloudgamer的js工具代码就很好理解了,加入支持defaultView的话,那肯定不支持contain方法,那么就使用compareDocumentPosition与16作位与操作只要大于等于16,结果肯定不是0啦;否则就使用ie的contain方法来进行判断就ok
四 nodeType nodeName nodeValue
节点类型 - 返回值
对于每种节点类型,nodeName 和 nodeValue 属性的返回值:
节点类型 | nodeName 返回 | nodeValue 返回
1 Element 元素名 null
2 Attr 属性名称 属性值
3 Text #text 节点的内容
4 CDATASection #cdata-section 节点的内容
5 EntityReference 实体引用名称 null
6 Entity 实体名称 null
7 ProcessingInstruction target 节点的内容
8 Comment #comment 注释文本
9 Document #document null
10 DocumentType 文档类型名称 null
11 DocumentFragment #document 片段 null
12 Notation 符号名称 null
五array方法
JS中的数组提供了四个操作,以便让我们实现队列与堆栈!
队列:先进先出
堆栈:后进先出
实现队列的方法:
shift:从集合中把第一个元素删除,并返回这个元素的值。
unshift: 在集合开头添加一个或更多元素,并返回新的长度
push:在集合末尾中添加元素,并返回新的长度
pop:从集合中把最后一个元素删除,并返回这个元素的值。
//有序数组去重函数
function quchong(results){
var elem,i=0,j;
var duplicates = [];
while ( (elem = results[i++]) ) {
console.log("i:" + i ); //从1开始
if ( elem === results[ i ] ) {
j = duplicates.push( i ); //返回duplicates长度
}
console.log("i:" + i );
}
while ( j-- ) {
results.splice( duplicates[ j ], 1 );
}
}
var results = [1,2,3,3,4,4,4,5];
quchong(results);
console.log(results);//[1,2,3,4,5]
六 document相关属性
documentObject.documentElement
返回documentElement 属性可返回文档的根节点。
document.getElementById("demo").ownerDocument;
返回元素的 ownerDocument:
定义和用法
ownerDocument 属性以 Document 对象的形式返回节点的 owner document。
在 HTML 中,HTML 文档本身始终是元素的 ownerDocument。