CSS Layout Debugger
https://gist.github.com/addyosmani/fd3999ea7fce242756b1
現(xiàn)在到處都是JavaScript爆阶,每天都能知道點(diǎn)新東西寿桨。一旦你入了門劈伴,你總能從這里或是那里領(lǐng)悟到很多知識(shí)痕支。一旦我發(fā)現(xiàn)一些有意思的東西搬素,我喜歡去感覺他們的源代碼,看一看它是怎么辦到的闯冷。
今天我想分享Addy Osmani的一行代碼 铐维,這行代碼對于你調(diào)試你的CSS是很有用的。為了可讀性童叠,我把它變成了3行框喳。
[].forEach.call($$("*"),function(a){
a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)
})
*注:Addy Osmani 是Google Chrome開發(fā)工程師,他前幾天開發(fā)的字符串解析模板, 馬上被兼容最新ES6標(biāo)準(zhǔn)的io.js采納拯钻。 *
嘗試在你瀏覽器的Console(F12)中運(yùn)行一下帖努,你會(huì)發(fā)現(xiàn)頁面被不同的顏色塊高亮了,這個(gè)方法非常簡單粪般,但是你自己寫的話可能產(chǎn)生非常多的代碼拼余,讓我們來研究一下它是怎么實(shí)現(xiàn)的。
選擇一個(gè)頁面上的所有元素
我們首先需要選擇頁面上的所有元素亩歹。Addy使用了只能在console調(diào)試工具中使用的$$
函數(shù)匙监,你可以在console中輸入$$('a')
自己試一下凡橱。它會(huì)返回當(dāng)前頁面的所有anchor(鏈接)元素。
$$
與document.querySelectorAll
是等價(jià)的亭姥。所以$$('*')
與 document.querySelectorAll('*')
是等價(jià)的稼钩,有興趣的話可以看看$ $和$選擇器的歷史。
對于我來說达罗,$$
的使用已經(jīng)讓我學(xué)到了很多坝撑。但是選擇頁面上的所有元素的知識(shí)還有很多。Mathias Bynens就在評論中指出document.all
其實(shí)也能選取選用元素粮揉,而且兼容所有主流瀏覽器巡李。
遍歷所有的元素
現(xiàn)在我們有了一個(gè)所有元素的節(jié)點(diǎn)列表(NodeList),現(xiàn)在我們想遍歷它們,并給他們加上有顏色的邊框扶认。我們先看看能從這行代碼里發(fā)現(xiàn)什么:
[].forEach.call( $$('*'), function( element ) { /* And the modification code here */ });
NodeList看起來像一個(gè)Array(數(shù)組)侨拦,你可以使用中括號來訪問他們的節(jié)點(diǎn),而且你還可以通過length
屬性知道它有多少元素辐宾。但是它并沒有實(shí)現(xiàn)Array的所有接口狱从,因此使用 $$('*').forEach 會(huì)返回錯(cuò)誤。
在JavaScript的世界里叠纹,有一堆看起來像Array但其實(shí)不是的對象季研。如function中的arguments對象。因此在他們身上通過call
和apply
來應(yīng)用數(shù)組的方法是非常有用的吊洼。我之前寫過一篇文章來解析它們的用法训貌,下面是一個(gè)例子:
function say(name) {
console.log( this + ' ' + name );
}
say.call( 'hola', 'Mike' ); // 打印輸出 'hola Mike'
// Also you can use it on the arguments object
function example( arg1, arg2, arg3 ) {
return Array.prototype.slice.call(arguments, 1); // Returns [arg2, arg3]
}
之前的一行代碼使用[].forEach.call
代替 Array.prototype.forEach.call
減少了代碼的編寫量 ( 另外一個(gè)很有意思的地方 );如果$$('*')
返回是個(gè)數(shù)組的話冒窍,它與$$('*').forEach
是等價(jià)的。如果你看看評論豺鼻,還有人使用for(i=0;A=$$('*');)
讓代碼變得更短综液,但是它在全局對象中注入了變量。你可以帶上var
聲明儒飒,如
for(var i=0,B=document.querySelectorAll('*');A=B[i++];){ /* your code here */ }
其中i
和B
將只聲明在console的上下文中谬莹。
改變元素的顏色
讓元素有一個(gè)漂亮的邊框,這行代碼使用了CSS的outline
屬性桩了。有一點(diǎn)你可能不知道附帽,在CSS渲染的盒子模型(Box Model)中,outline
并不會(huì)改變元素及其布局的位置井誉。因此這比使用border屬性要好得多蕉扮,所以這一部分其實(shí)并不難理解
a.style.outline="1px solid #" + color
怎樣定義顏色值其實(shí)是比較有意思的~~
(Math.random()*(1<<24))).toString(16);
我們想構(gòu)造的其實(shí)是一個(gè)16進(jìn)制的顏色值,像白色FFFFFF
颗圣,藍(lán)色0000FF
等等喳钟。首先我們學(xué)到了可以使用數(shù)字類型的toString()
方法進(jìn)行十進(jìn)制到16進(jìn)制的轉(zhuǎn)換屁使。其實(shí)你可以用它進(jìn)行任意進(jìn)制的轉(zhuǎn)換:
(30).toString(); // "30"
(30).toString(10); // "30"
(30).toString(16); // "1e" 16進(jìn)制
(30).toString(2); // "11110" 二進(jìn)制
(30).toString(36); // "u" 36 是最大允許的進(jìn)制
另一方面,你可以使用parseInt()
方法的第二個(gè)參數(shù)奔则,將十六進(jìn)制數(shù)轉(zhuǎn)換為十進(jìn)制:
parseInt("30"); // "30"
parseInt("30", 10); // "30"
parseInt("1e", 16); // "30"
parseInt("11110", 2); // "30"
parseInt("u", 36); // "30"
我們需要一個(gè)在0到ffffff之間的十六進(jìn)制數(shù)蛮寂,也就是parseInt("ffffff", 16) == 16777215
,16777215正是2^24 - 1的值易茬。
二進(jìn)制中酬蹋,每次在1的右面加0,實(shí)際就是在做2^n運(yùn)算抽莱,n就是0的個(gè)數(shù)范抓。
1 // 1 == 2^0
100 // 4 == 2^2
10000 // 16 == 2^4
1000000000000000000000000 // 16777216 == 2^24
左移運(yùn)算 x << n
就是在二進(jìn)制數(shù) x 的右邊添加 n 個(gè) 0,1 << 24
就是16777216的簡便寫法岸蜗。
Math.random()
返回取值范圍 [ 0 , 1 ) 內(nèi)的偽隨機(jī)數(shù)尉咕。
var a = Math.random()*2+1 //設(shè)置一個(gè)隨機(jī)1到3 (取不到3) 的變量
Math.random()*(1<<24)
就可以得到一個(gè) 0 到 16777216之間的值。
但是Math.random
返回的是一個(gè)浮點(diǎn)數(shù)字璃岳,我們只需要整數(shù)部年缎,這里使用了“~”操作符(按位取反操作)。
這里并不關(guān)心正負(fù)值铃慷,它利用“”按位操作丟棄小數(shù)部分单芜。因此通過兩次取反就可以得到純整數(shù)部,我們還可以將“~”視為parseInt的簡寫:
var a = 12.34; // ~~a = 12
var b = -1231.8754; // ~~b = -1231
var c = 3213.000001; // ~~c = 3213
~~a == parseInt(a, 10); // true
~~b == parseInt(b, 10); // true
~~c == parseInt(c, 10); // true
如果你仔細(xì)看原文評論犁柜,你會(huì)知道使用 按位或 "|"操作符也可以去掉小數(shù)部分洲鸠。
~~a == 0|a == parseInt(a, 10);
~~b == 0|b == parseInt(b, 10);
~~c == 0|c == parseInt(c, 10);
我們最終得到了一個(gè) 0 到 16777216之間的隨機(jī)數(shù),也就是需要的隨機(jī)顏色馋缅,使用toString(16)
轉(zhuǎn)換成16進(jìn)制就可以運(yùn)行了扒腕。
github:Addy Osmani,原文鏈接:arqex.com萤悴,翻譯鏈接:ourjs.com