近幾日,氣壓猛降,霧霾鋪天蓋地,眼看一場腥風血雨就要在前端江湖爆發,這場戰爭不僅是百度、騰訊、阿狸、搜狐網易新浪等江湖豪門搶奪人才的大戰,也是諸位江湖人士重新洗牌的好時機。每年10月,江湖的波動勝過華山論劍、五岳爭主。如今這江湖人才濟濟,新門派如雨后春筍,江湖高手更是各個身懷絕技。在博客園這個擂台上更是齊聚各路高手。本人wisdomoon是一名懶人,沒有"湯姆大叔"的蓋世神功,也沒有"T2噬菌體"的嚴謹細膩,更沒有"Aaron"的精益求精,因此本人為大家獻上的不是怒秀技巧的《葵花寶典》、不是移花接木的《辟邪劍譜》、也不是磨礪內力的《易筋經》而是"投機取巧"的《前端面霸系列》。閱完此系列,諸位會略知各門派開山祖師的入門絕技,如果運用自如,能順利潛入任何門派,到時學一家之長不在話下。
由於是第一篇,以上所述就當引言。本秘籍將采用Q&A(Question and Answer)的方式帶大家一覽各派問題。本文更適合前端的浪子閱讀,如大師偶讀此文,可多賜教。
Q:doctype的作用是什么,你知道多少種類型的doctype
A: 最簡單也最常見的回答是:doctype是DocumentType的簡稱即文檔類型,常見的有 Strict、Transitional 以及 Frameset 三種。一般一個問題后面會有"為什么"、"會導致什么",這才是這道題目的關鍵。文檔為什么要分類型?如果文檔不分類型,各瀏覽器就會形成多種寫法,假如IE用<title>標簽作為標題、火狐瀏覽器用<caption>標簽作為標題,而另一種瀏覽器可能采用<mytitle>,這對於開發者和用戶來說簡直是災難。這時候神僧W3C(萬維網聯盟World Wide Web Consortium)已經把自己偷偷熬夜制作的對所有方面都平衡的分歧解決方案拿了出來,各瀏覽器一看內心計算片刻之后紛紛表示沒有異議。於是我們用<!doctype>(注意:作為一個特殊的標簽,它是不需要閉合的)標簽來引入W3C的dtd文件,以達到規范頁面的效果。此舉壯大了w3c組織,同時、瀏覽器的文檔標准的統一也為開發人員和用戶帶了了便利。 這里需要提出的是html5不是基於SGML實現的,因此html不需要引入DTD,所以html5可以簡單的聲明一下<!doctype html>。
Q:如果不聲明doctype?
A:這也就是上面所述的"會導致什么"。如果不聲明doctype,瀏覽器不引入w3c的標准,那么早期的瀏覽器會按照自己的解析方式渲染頁面。我們把不使用w3c標准解析,采用自身方式解析頁面的行為稱為"quirks mode",相反的,采用w3c方式解析就是"strict mode"也就是我們說的"standards mode"。我們知道凡事不可能太完美,如果完全采用strictmode那么不允許出任何的差錯,這樣會降低程序的容錯率,加重開發人員的難度,因此在standards mode 里面我們又分出來 Almost Standards Mode(接近標准模式),如下圖:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN "http://www.w3.org/TR/html4/loose.dtd">在html4中我們引入最多的就是接近標准的Transitional 文檔類型。這兩個問題考察了我們是否深入理解doctype的類型,是否理解瀏覽器的解析和渲染規則。還請多多揣摩。
這個問題的最直接答案是:不寫doctype,瀏覽器會進入quirks mode (混雜模式)
Q:如何判斷瀏覽使用哪種方式解析css
A:這其實是上面問題的復習和延伸。直接給出答案:
1、沒有doctype聲明的采用quirks mode解析
2、對於有doctype的大多數采用standard mord(這里為什么用大多數,請讀者思考,請參考http://hsivonen.iki.fi/doctype/)
3、特殊情況:
a、對於那些瀏覽器不能識別的doctype ,瀏覽器采用quirks mode
b、沒有聲明DTD或者html版本聲明低於4.0采用quirks mode其他使用standard mode
c、你能看到的現在的大多數網頁采用的是standard mode
d、ie6中,如果在doctype聲明前有一個xml聲明(比如:<?xml version="1.0" encoding="iso-8859-1"?>),則采用quirks mode解析。(這點估計連面試官都沒 注意)
Q:說出quirks mode 和 strict mode 在瀏覽器上的表現差異?
A:他們最大的不同是對盒模型(由於本人對盒模型理解模糊,再加上盒模型是筆試、面試常見題目,后面會專門來一期一期探討)的解析。
在strict mode中 :width是內容寬度 ,也就是說,元素真正的寬度 = margin-left + border-left-width + padding-left + width + padding-right + border-right- width + margin-right;
在quirks mode中 :width則是元素的實際寬度 ,內容寬度 = width - (margin-left + margin-right + padding-left + padding-right + border-left-width + border-right-width)
Q:js如何判斷瀏覽器正在以何種方式解析?
A:這道問題的答案很簡答,但是重要的往往不是答案。重要的是要知道為什么?"到底是為什們呢?"這是我和朋友最喜歡開玩笑的口語,再以后的文中會經常遇到。好了,回歸正傳,這里打算用一個例子說明。
jiathis的源代碼中有如下細節:
var d = document, isStrict = d.compatMode == "CSS1Compat", dd = d.documentElement, db = d.body /*省略一部分無關代碼*/ return { h: (isStrict ? dd : db).clientHeight, w: (isStrict ? dd : db).clientWidth }
看到這里本題的答案也出來了使用 document.compatMode來判斷瀏覽器的解析方式,代碼如下
function getMode{ var _cm = docoment.compatMode; if(_cm == 'CSS1Compat'){ return "strict" } if(_cm == 'BackCompat' ){ return 'quirks' } }
在quirks 模式下,下document.documentElement無法正確取到clietHeight scrollHeight等值,比如clietHeight=0,此時計算頁面高度的時候需要用document.body來代替
document.documentElement. 如果頁面開發者忘了寫<!doctype>或者書寫有誤,那么計算頁面可見區域高度時最好做如上判斷。很多源代碼計算頁面高度的時候都使用了和jiathis類似的處理方式。
補充一下document.body是DOM中Document對象里的body節點, document.documentElement是文檔對象根節點(html)的引用。 document.body.scrollHeight是body元素的滾動高度,document.documentElement.scrollHeight為頁面的滾動高度。
Q:何時使用document.body 何時使用document.documentElement
A:這是免費送大禮,看了上面的同志都輕而易舉。
