從一行代碼裏面學點 JavaScript

摘要:從一行代碼裏面學點JavaScript,現現在,JavaScript無處不在,所以關於JavaScript的新知識也是層出不窮。JavaScript的特色在於,要學習它的語法入門簡簡單,可是要精通使用它的方式倒是一件不容易的事。javascript

現現在,JavaScript無處不在,所以關於JavaScript的新知識也是層出不窮。JavaScript的特色在於,要學習它的語法入門簡簡單,可是要精通使用它的方式倒是一件不容易的事。java

來看看下面的這段代碼,它來自於谷歌「名猿」Addy Osmani在幾天前貼出的一段代碼,它的做用是用來調試你的CSS層。所有代碼只有三行,可是你絕對能夠把它放在一行裏面完成:程序員

[].forEach.call($$("*"),function(a){

  a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)

})

如今,在你的Chrome瀏覽器的控制檯中輸入這段代碼,你會發現不一樣HTML層都被使用不一樣的顏色添加了一個高亮的邊框。是否是很是酷?可是,簡單來講,這段代碼只是首先獲取了全部的頁面元素,而後使用一個不一樣的顏色爲它們添加了一個1ps的邊框。想法很簡單,可是真要實現起來卻不是那麼容易的一件事。在下面的內容中,咱們將一塊兒一步一步學習如何理解上面的這段代碼。數組

選擇頁面中全部的元素

咱們須要作的第一件事情是獲取頁面中全部的元素,在上面的代碼中,Addy使用了一個Chrome瀏覽器中特有的函數 $$。你能夠在你的Chrome瀏覽器控制檯中輸入 $$('a'),而後你就能獲得一個當前頁面中全部錨元素的列表。瀏覽器

$$函數是許多現代瀏覽器命令行API中的一個部分,它等價於 document.querySelectorAll,你能夠將一個CSS選擇器做爲這個函數的參數,而後你就可以得到當前頁面中全部匹配這個CSS選擇器的元素列表。若是你在瀏覽器控制檯之外的地方,你可使用 document.querySelectorAll('*') 來代替 $$('*')。更多關於 $$ 函數的詳細內容能夠查看Chrome開發者工具的文檔。app

固然,除了使用$$函數以外,咱們還有一種更簡單的方法,document.all,雖然這並非一種很規範的使用方法,可是它幾乎在每個瀏覽器中都能運行成功。dom

迭代全部的元素

通過第一步,咱們已經得到了頁面內全部的元素,如今咱們想作的事情是遍歷每個元素,而後爲它們添加一個彩色邊邊框。可是上面的代碼到底是怎麼一回事呢?函數

[].forEach.call( $$('*'), function( element ) { /* 在這裏修改顏色 */ });

首先,咱們經過選擇器得到的列表是一個NodeLists對象,它和JavaScript中的數組有點像,你可使用方括號來獲取其中的節點,你也能夠檢查它其中包含多少個元素,可是它並無實現數組包含的全部方法,所以咱們並不能使用$$('*').forEach()來進行迭代。在JavaScript中,有好幾個相似於數組可是並非數組的對象,除了前面的NodeLists,還有函數的參數集合arguments,在這裏咱們可使用call或apply函數將函數的方法運用到這些對象上。例以下面的例子:工具

function say(name) {

 console.log( this + ' ' + name );

}

say.call( 'hola', 'Mike' ); // 打印 'hola Mike'

// 你也能夠將這種方法有用在arguments對象上 function example( arg1, arg2, arg3 ) { return Array.prototype.slice.call(arguments, 1); // Returns [arg2, arg3] }

在Addy的代碼中,使用了[].forEach.call而不是Array.prototype.forEach.call,兩者等價,可是前者能夠節省幾個字節。佈局

爲元素添加顏色

爲了讓元素都有一個漂亮的邊框,咱們在上面的代碼中使用了CSS屬性outline。outline屬性位於CSS盒模型以外,所以它並不影響元素的屬性或者元素在佈局中的位置,這對於咱們來講很是有用。這個屬性和修改border屬性很是相似,所以下面的代碼應該不會很難理解:

a.style.outline="1px solid #" + color

真正有趣的地方在於定義顏色部分:

~~(Math.random()*(1<<24))).toString(16)

天吶,上面的代碼是什麼意思?在JavaScript中,比特操做符並非常常被使用,所以這裏可能會讓不少程序員感到很疑惑。

咱們想達到的目的是活的一個十六進制格式的顏色例如白色對應的是FFFFFF,藍色對應的是0000FF,或者隨便一個顏色37f9ac。雖然咱們人類喜歡十進制,可是咱們的代碼經常會須要十六進制的東西。

咱們首先要學會如何使用toString函數將一個十進制的數組轉換爲一個十六進制整數。這個函數能夠接受一個參數,若是參數缺省,默認爲十進制,可是你徹底可使用別的數組:

(30).toString(); // "30"

(30).toString(10); // "30"

(30).toString(16); // "1e" 十六進制

(30).toString(2); // "11110" 二進制

(30).toString(36); // "u" 36是容許的最大參數值

除此以外,你可使用parseInt函數將十六進制數字轉換爲十進制。

parseInt("30"); // "30"

parseInt("30", 10); // "30"

parseInt("1e", 16); // "30"

parseInt("11110", 2); // "30"

parseInt("u", 36); // "30"

所以,咱們如今只須要一個位於0和ffffff之間的十六進制數,因爲:

parseInt("ffffff", 16) == 16777215

而這裏的16777215其實是2^24-1。

若是你對二進制數學熟悉的話,你可能會知道1<<24 == 16777216。

再進一步,你每在1後面添加一個0,你就至關於多作了一次2的乘方:

1 // 1 == 2^0

100 // 4 == 2^2

10000 // 16 == 2^4

1000000000000000000000000 // 16777216 == 2^24

所以,在這裏咱們能夠知道Math.random()*(1<<24)表示一個位於0和16777216之間的數。

可是這裏並無結束,由於Math.random返回的是一個浮點數,可是咱們只想要整數部分。咱們的代碼中使用波浪號操做符來完成這件事。波浪操做符在JavaScript中被用來對一個變量進行取反。

可是咱們在這裏並不關心取反,咱們指向獲取整數部分。所以咱們還能夠知道兩次取反能夠去掉一個浮點數的小數部分,所以~~的做用至關於parseInt:

var a = 12.34, // ~~a = 12

    b = -1231.8754, // ~~b = -1231

    c = 3213.000001 // ~~c = 3213

;



~~a == parseInt(a, 10); // true

~~b == parseInt(b, 10); // true

~~c == parseInt(c, 10); // true

固然,咱們還有一種更加簡潔的方法,使用OR操做符:

~~a == 0|a == parseInt(a, 10)

~~b == 0|b == parseInt(b, 10)

~~c == 0|c == parseInt(c, 10)

最終,咱們得到了一個位於0和16777216之間的隨機整數,也就是咱們想要的隨機顏色。此時咱們只須要使用toString(16)將它轉化爲十六進制數便可。

總結

如今,你已經徹底理解了前面的這一行代碼中的各個部分。做爲一個程序員,咱們應該在完成工做以後多問本身幾遍爲何,還有沒有更好更簡潔的方法。固然,最應該作的事情固然是多閱讀程序代碼,也許你就能從某一行代碼中學到不少新東西。

做者:野狗
原文連接:Learning much javascript from one line of code

相關文章
相關標籤/搜索