读jQuery源码释疑笔记
本釋疑筆記是針對自己在看源碼的過程中遇到的一些問題的解答,對大眾可能不具有參考性,不過可以看看有沒有你也不懂得地方,相互學習,相互進步。
?1、each的用法
之前對each的用法一直迷迷糊糊,這次終于懂了。
源碼:
each: function( obj, callback, args ) {var value,i = 0,length = obj.length,isArray = isArraylike( obj );if ( args ) {if ( isArray ) {for ( ; i < length; i++ ) {value = callback.apply( obj[ i ], args );if ( value === false ) {break;}}} else {for ( i in obj ) {value = callback.apply( obj[ i ], args );if ( value === false ) {break;}}}// A special, fast, case for the most common use of each} else {if ( isArray ) {for ( ; i < length; i++ ) {value = callback.call( obj[ i ], i, obj[ i ] );if ( value === false ) {break;}}} else {for ( i in obj ) {value = callback.call( obj[ i ], i, obj[ i ] );if ( value === false ) {break;}}}}return obj;}, View Codeeach函數可以傳進去三個參數,第一個是對象或者數組,第二個是回調函數,第三個同樣是數組或者對象
實例:
var t={name:"t",age:"t1"};var tt=[1,2,3];$.each(t,function(j){console.log(j); //1; 1 每次迭代輸出一個值 },tt)$.each(tt,function(j){console.log(j); //1; 1},t)//undefinded ;undefined ;undefined 每次迭代輸出一個值 $.each(t,function(j){console.log(j); //name; age })$.each(t,function(i,j){console.log(i+" "+j);//name t; age t1 })$.each(tt,function(i,j){console.log(i+" "+j);//0 1; 1 2; 2 3;})?jQuery中經常采用each的方式為來創建函數。
?
依次迭代數組中的元素,為其綁定方法,省力且簡單易懂。
?
2、一個等式
var name="t"; var getByName = typeof name === "string"; // name必須是字符串 console.log(getByName); //true console.log(name); //t//類似的還出現在access函數中。
bulk = key == null;
?3、exec() 方法用于檢索字符串中的正則表達式的匹配。
exec() 方法用于檢索字符串中的正則表達式的匹配。返回一個數組,其中存放匹配的結果。如果未找到匹配,則返回值為 null。
如果 exec() 找到了匹配的文本,則返回一個結果數組。否則,返回 null。此數組的第 0 個元素是與正則表達式相匹配的文本,第 1 個元素是與 RegExpObject 的第 1 個子表達式相匹配的文本(如果有的話),第 2 個元素是與 RegExpObject 的第 2 個子表達式相匹配的文本(如果有的話),以此類推。除了數組元素和 length 屬性之外,exec() 方法還返回兩個屬性。index 屬性聲明的是匹配文本的第一個字符的位置。input 屬性則存放的是被檢索的字符串 string。我們可以看得出,在調用非全局的 RegExp 對象的 exec() 方法時,返回的數組與調用方法 String.match() 返回的數組是相同的。
但是,當 RegExpObject 是一個全局正則表達式時,exec() 的行為就稍微復雜一些。它會在 RegExpObject 的 lastIndex 屬性指定的字符處開始檢索字符串 string。當 exec() 找到了與表達式相匹配的文本時,在匹配后,它將把 RegExpObject 的 lastIndex 屬性設置為匹配文本的最后一個字符的下一個位置。這就是說,您可以通過反復調用 exec() 方法來遍歷字符串中的所有匹配文本。當 exec() 再也找不到匹配的文本時,它將返回 null,并把 lastIndex 屬性重置為 0。
var str = "Visit W3School"; var patt = new RegExp("W3School","g"); var result;while ((result = patt.exec(str)) != null) {document.write(result);document.write("<br />");document.write(patt.lastIndex);}輸出: W3School 14rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/;
var str = ' <div id=top></div>';
var match = rquickExpr.exec(str);
console.log(match)
//[" <div id=top></div>", "<div id=top></div>", undefined, index: 0, input: " <div id=top></div>"]
var str = '#test';
var match = rquickExpr.exec(str);
console.log(match[1])//undefined
rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)/,這里后面\1的用法。\1類似replace時候用的′/,這里后面\1的用法。\1類似replace時候用的′1',可以匹配第一個子匹配
?之所以會有undefined,是因為最后的那個#不匹配,也就是沒有找到。找的順序是先從第一個小括號開始找起,然后再開始第二個小括號,哪怕第二個小括號在第一個小括號里面。
match數組從0開始標記,match[0],代表第一個匹配的內容。也就是index的值,表示第一次匹配的地方。
4、ownerDocument和 documentElement的區別
- ownerDocument是Node對象的一個屬性,返回的是某個元素的根節點文檔對象:即document對象
- documentElement是Document對象的屬性,返回的是文檔根節點
- 對于HTML文檔來說,documentElement是<html>標簽對應的Element對象,ownerDocument是document對象
?
5、jQuery.parseHTML
使用原生的DOM元素的創建函數將字符串轉換為一組DOM元素,然后,可以插入到文檔中。
str = "hello, <b>my name is</b> jQuery.", html = $.parseHTML( str ),?6、strundefined = typeof undefined
將undefined類型轉化為字符串,用于判斷
strundefined = typeof undefined,console.log(strundefined+" "+$.type(strundefined));//undeined string?7、節點關系
其實不難發現,一個節點跟另一個節點有以下幾種關系:祖宗和后代,父親和兒子,臨近兄弟,普通兄弟。
在CSS選擇器里邊分別是用:空格;>;+;~
(其實還有一種關系:div.aaron,中間沒有空格表示了選取一個class為aaron的div節點)爺爺grandfather與孫子child1屬于祖宗與后代關系(空格表達)
- 父親father與兒子child1屬于父子關系,也算是祖先與后代關系(>表達)
- 哥哥child1與弟弟child2屬于臨近兄弟關系(+表達)
- 哥哥child1與弟弟child2,弟弟child3都屬于普通兄弟關系(~表達)
?
8、value.match( core_rnotwhite )
閱讀源碼的過程中,經常會遇到
classNames = value.match( core_rnotwhite ) || [];
//core_rnotwhite = /\S+/g ,匹配任意不是空白符的字符串
match返回的是一個數組,因此如果不滿足的話,就返回空數組
等類似的表達,其實就是將 value 用空格分開成一個數組,相當于 classes = (value || "").split("/\s+/")
?
9、函數的傳入參數為空和“”之間的區別
?
$("#one").removeClass("");console.log( $('#one').attr('class') );//1 huanshen huansky$("#one").removeClass();console.log( $('#one').attr('class') );// var t=null ? 1 : 0;console.log(t);//0var t=" " ? 1 : 0;console.log(t);//1var t="" ? 1 : 0;console.log(t);//0function sum(){console.log(arguments.length);//1 };sum("");?
傳入參數為“”的時候,arguments.length的值等于1,其實就是有一個參數傳進去,哪怕是“”,但是不傳參數的時候,arguments.length=0;
removeClass不傳入參數的時候,就將所有的class都移除
?10、on,bind,delegate,live
其實.bind(), .live(), .delegate()都是通過.on()來實現的,.unbind(), .die(), .undelegate(),也是一樣的都是通過.off()來實現的。提供了一種統一綁定事件的方法
.delegate()就是事件委托
$('#element).delegate('a', 'click', function() { alert("!!!") });?.bind ? ? ??$('#foo').bind('click',function(){ })
.live(),將委托的事件處理程序附加到一個頁面的document元素,從而簡化了在頁面上動態添加的內容上事件處理的使用。現在已經被廢棄了,?
$('a').live('click', function() { alert("!!!") });?one,只觸發一次
one: function( types, selector, data, fn ) {return this.on( types, selector, data, fn, 1 ); },直接采用on的委托事件
$('.ul').on('click', 'a', function(e){ alert('click event');});.bind()方法用于直接附加一個事件處理程序到元素上。
總結:
在下列情況下,應該使用.delegate(),而不能使用.bind():
- 為DOM中的很多元素綁定相同事件;
- 為DOM中尚不存在的元素綁定事件;
用.bind()的代價是非常大的,它會把相同的一個事件處理程序hook到所有匹配的DOM元素上
.delegate()會提供很好的方法來提高效率,同時我們可以添加一事件處理方法到動態添加的元素上
我們可以用.on()來代替上述的3種方法
不足點也是有的:
- 并非所有的事件都能冒泡,如load, change, submit, focus, blur
- 加大管理復雜。
- 不好模擬用戶觸發事件
如何取舍就看項目實際中運用了。
?
總結
以上是生活随笔為你收集整理的读jQuery源码释疑笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: github的一些简单用法
- 下一篇: java动态编译