“聲討”高云的《jQuery技術(shù)內(nèi)幕》
1. 前言:
其實(shí)本文有點(diǎn)太標(biāo)題黨了,哈哈,見(jiàn)諒。說(shuō)“聲討”,就是說(shuō)說(shuō)我作為一個(gè)《jQuery技術(shù)內(nèi)幕》一個(gè)忠實(shí)讀者,讀本書(shū)的一些想法和建議。
2014年2月20日,我收到了《jQuery技術(shù)內(nèi)幕》,密密麻麻600多頁(yè)。到今天4月9日,我已經(jīng)看了400多頁(yè)(除卻sizzle的一部分沒(méi)看,因?yàn)槟菈K實(shí)在是看不懂,就先略過(guò))。
我買(mǎi)了書(shū),當(dāng)時(shí)花了大約80元,而且認(rèn)認(rèn)真真的看了一大半,后面的部分我還會(huì)繼續(xù)看下去。也算是一個(gè)忠實(shí)的讀者。
學(xué)習(xí)新知識(shí),總是一個(gè)痛苦的過(guò)程,期間也是痛并快樂(lè)著。總結(jié)痛苦的原因,一方面解讀jQuery源碼確實(shí)是一個(gè)龐大的工程,另一方面,也覺(jué)得作者在寫(xiě)書(shū)的時(shí)候漏掉了許多。
書(shū)看了一半多,總是想著寫(xiě)點(diǎn)什么。想來(lái)想去,印象最深的,是覺(jué)得作者沒(méi)有給讀者一個(gè)“臺(tái)階”,而是直接拔高到了源碼的層面,一行一行的解讀、注釋。詳細(xì)解讀源碼并沒(méi)有什么不好,但是在解讀每行的源碼之前,應(yīng)該想說(shuō)點(diǎn)什么,把讀者帶進(jìn)去。
下面我說(shuō)幾個(gè)例子:
例1. jQuery('div')到底是個(gè)什么對(duì)象?
本書(shū)一上來(lái)就是構(gòu)建jQuery對(duì)象,列出了N中構(gòu)建jQuery對(duì)象的方式,有DOM元素、字符串、函數(shù)等等。但是讀者看了好大一部分篇幅之后,都不知道這些構(gòu)建的對(duì)象,到底是什么?這些代碼的最終結(jié)果是什么?到底為誰(shuí)服務(wù)?以及對(duì)Jquery對(duì)象進(jìn)行各種操作的時(shí)候,由于不明白它的結(jié)構(gòu)而產(chǎn)生迷惑。
恰巧,當(dāng)時(shí)我在看這本書(shū)的同時(shí),也正在看miaov.com的視頻教程,教程里面的講師就及早的提到了這一點(diǎn)。例如:
jQuery('div')返回的,其實(shí)是一個(gè)對(duì)象,加入頁(yè)面中有3個(gè)div元素,那么這個(gè)對(duì)象就會(huì)創(chuàng)建“0”、“1”、“2”這三個(gè)屬性,分別指向這三個(gè)DOM對(duì)象,length屬性記錄個(gè)數(shù)。這樣就不會(huì)讓我們誤以為jQuery('div')是一個(gè)數(shù)組。

我當(dāng)時(shí)問(wèn)過(guò)許多人,jQuery('div')是個(gè)什么對(duì)象,他們都誤以為是一個(gè)數(shù)組,后來(lái)我跟他們說(shuō)jQuery('div')是一個(gè)object,不是數(shù)組。
(題外話:jQuery('div')既然是object,那么JSON.stringify(jQuery('div'))會(huì)出錯(cuò),為什么?因?yàn)閖Query('div')里面的DOM元素存在著循環(huán)引用。)
有些人可能會(huì)說(shuō):那是你自己懶,你不會(huì)去chrome中跟蹤以下嗎? 如果非要那么嚴(yán)格要求讀者,就繼續(xù)看下一例子。
例2. 屬性操作中,“修正對(duì)象”是什么?
記得當(dāng)時(shí)看這一段的時(shí)候,我都懵了,從來(lái)沒(méi)接觸過(guò)“修正對(duì)象”這個(gè)概念,滿篇提到的get,set到底是什么東西?
現(xiàn)在回頭再看,這些問(wèn)題確實(shí)迎刃而解,但是當(dāng)時(shí)確實(shí)不知道,于是就湊合著往前看,終于看到最后才算明白了,修正對(duì)象就是為了解決瀏覽器兼容性,分離除了的處理瀏覽器“個(gè)性”需求的方法。
一般情況下的html/DOM屬性操作,可能通過(guò)簡(jiǎn)單的賦值或者設(shè)置就可以完成,但是有一些是需要照顧瀏覽器個(gè)性的,例如瀏覽器不支持getAttribute()該怎么辦,更多例子可參見(jiàn)jQuery.support。jQuery把這些特殊情況,分離出來(lái),集中到一個(gè)叫做“修正對(duì)象”的對(duì)象中,通過(guò)設(shè)置set和get來(lái)操作。因此,在獲取一個(gè)html/DOM屬性時(shí),jQuery會(huì)先檢查是否符合修正對(duì)象里的情況,如果符合就調(diào)用get來(lái)返回值,如果不符合,就用最基本的操作返回值。
如果本書(shū)在該章節(jié)前面,加這樣一段解釋?zhuān)岳踊蛘吡鞒虉D的形式展示更好,先把修正對(duì)象、get、set、的意義大體說(shuō)一遍,讓讀者心里有個(gè)譜,我想讀起來(lái)會(huì)輕松許多。
例3. jQuery的事件存儲(chǔ)結(jié)構(gòu)是怎樣的?
正是我現(xiàn)在看的章節(jié),現(xiàn)在才算稍微明白一點(diǎn)。書(shū)中之前介紹過(guò),事件存儲(chǔ)在jQuery.cache中,不是直接用div1.onclick=function(){...}的方式。但是寫(xiě)到事件這一章節(jié),沒(méi)有再深入介紹,即直接上來(lái)代碼解釋了。看它代碼中各種取值賦值,看的很難受,不知道從哪里取出,也不知道賦值到哪里去。
我覺(jué)得我現(xiàn)在像是個(gè)警察再查找一個(gè)案件的線索一樣,探尋著代碼中的蛛絲馬跡,再加上自己看一些博客,才算稍微明白點(diǎn)事件的存儲(chǔ)結(jié)構(gòu),待完全明白估計(jì)得把這一章看完,然后再重新梳理一遍才行。
elemData = $.data(div1); //div1對(duì)應(yīng)的緩存 handle = elemData.handle; //主監(jiān)聽(tīng)函數(shù)(統(tǒng)一觸發(fā)、執(zhí)行其他函數(shù)) events = elemData.events; //elemData.events handlers = events["click"]; //click 對(duì)應(yīng)的監(jiān)聽(tīng)對(duì)象數(shù)組 handlers.push(handleObj); //監(jiān)聽(tīng)對(duì)象數(shù)組中存儲(chǔ)了若干個(gè)監(jiān)聽(tīng)對(duì)象 //handleObj又包含了事件類(lèi)型、觸發(fā)函數(shù)等等各類(lèi)信息
另外,還有一個(gè)重要信息:事件既然被jQuery給重新規(guī)定了格式,那么“事件冒泡”肯定是沒(méi)有了,怎么辦呢? jQuery在事件執(zhí)行的時(shí)候自己來(lái)模擬冒泡,這一點(diǎn)如果不明白,看代碼也會(huì)遇到許多疑惑。
總結(jié):
說(shuō)了這么多,我想大家也應(yīng)該明白我的意思了。
《技術(shù)內(nèi)幕》是一本很不錯(cuò)的書(shū),我也很佩服作者的功力,自己看著人家的書(shū),理解都那么費(fèi)勁,何況作者寫(xiě)書(shū)呢。
如果《技術(shù)內(nèi)幕》能夠出第二版,希望作者能采納我的建議,多加一些解釋性的東西,多加一些“臺(tái)階”。


浙公網(wǎng)安備 33010602011771號(hào)