第一章,概述
這章是綜述性質的,做者隨意的給出了一些例子。javascript
1. visibility = hidden, display = none。html
function hide (e, reflow) { if (reflow) { e.target.style.display = "none"; } else { e.target.style.visibility = "hidden"; } }
這段代碼展現了兩種隱藏節點的方式,以前在項目中接觸最多的是display=none,對visibility=hidden的方式沒用過,還不知道這種方式和display = none有什麼區別。
visibility = "hidden",元素會隱藏,可是不會把元素從渲染樹種拿掉,它依然會部分渲染,只是不可見而已(變成徹底透明,只會觸發repaint)。
display = "none",那麼元素就不會渲染,整個從渲染樹中拿掉了。會觸發reflow與repaint。
好比 java
中間的元素visibility = hiddennode
中間的元素display = nonegit
其實我想問爲何中間那個所謂只會觸發repaint的隱藏方式會傲嬌的多出來一截。。。。。。顯然這種狀況下瀏覽器會reflow的。想一想多是由於我用了自動寬度。果真,這樣就和諧多了。
使用固定寬度 github
2. Bind events with DOM node's "on" attributes。正則表達式
給DOM元素定義事件最簡單的方法是,給DOM節點以"on"爲前綴的屬性綁定一個回調。出於頁面維護性的考慮,這種代碼和HTML節點寫一起玩法正常狀況下不多會用到。 編程
<div style = "border: 1px solid gray" onmousedown="(function(node){node.textContent = new Date().toString();})(this);">點擊我文字會改變</div> <div style = "border: 1px solid gray" onmouseup="(function(event){event.target.textContent = new Date().toString();})(event);">點擊我文字會改變</div>
3. addEventListener。數組
玩的更多的應該仍是addEventListener。瀏覽器
<div id = "click_node">點擊我看看</div> <script> window.onload = function() { var node = document.getElementById('click_node'); if (node && node.addEventListener) { node.addEventListener('mousedown', function(){ node.textContent = "mouse down on node"; }, false); node.addEventListener('mouseup', function(event){ node.textContent = "mouse up on node"; }, false); } } </script>
注意幾個小問題,好比addEventListener的第一個參數是須要綁定的事件名,全小寫的,並且沒有」on」前綴。(若是兼容老版IE用attachEvent的話則須要加上on前綴)。第三個參數是用來指定是否把linstener註冊在事件的capture階段,通常都是false,也是使用element.onclick = function(){}這種綁定方式的的默認行爲。
關於DOM事件的生命週期,能夠參考一下這篇文章。這裏插一句,文章中提到經過阻止不必的事件冒泡能夠提高性能,不過做者提到的event.cancelBubble這種方式並不被提倡(參考),應該使用event.stopPropagation()來替代這種方式。
第二章,詞法結構
這章主要內容是JS程序的詞法構成,並無什麼須要特別注意的。
1. JavaScript會認爲它正在解析的程序代碼已是這種標準格式,不會再對標示符、字符串、正則表達式作標準化處理。
關於JavaScript與Unicode,我準備專門再寫一篇總結文章。這個Normalization問題有時候挺煩人的,特別是要對字符串作細緻處理的時候。ES6已經添加一個新方法String.prototype.normalize來提供這個功能,在此以前可使用一些庫來完成,好比unorm (https://github.com/walling/unorm)(by Bjarke Walling).
2. 在return、break、continue語句和隨後的表達式之間不能有換行。
不然會出現難以調試的程序問題。正常人應該都不會這麼寫的。
3. 「++」與「--」做爲後綴的時候要與表達式在同一行。
同上,正常人不會另起一行寫++--的。
第三章,類型、值和變量
1. JavaScript的數據類型分爲兩類:原始類型(primitive type)與對象類型。簡單(原始)類型(simple types)有numbers、strings、booleans、null 和 undefined。剩下的其餘的都是對象類型。
注意一下number、string、boolean是類對象(object-like)由於他們有一些預約義的方法,但它們是immutable的。
2. JS不區分整數和浮點數。全部的數字都是雙精度浮點數,採用IEEE 754標準。JS中實際的操做(好比數組索引、位操做)則是基於32位整數。
因爲是雙精度浮點數,因此有喜聞樂見的 0.1 + 0.2 != 0.3。任何採用二進制浮點數的編程語言都會有這個問題。
關於實際操做,好比位操做時使用32位整數, 寫代碼時能夠利用這個特性來把小數轉換成整數,參考我這篇文章,《javascript中小數轉換爲整數》。
IEEE 754 中關於雙精度浮點數的規定是1位數符、11位階碼再加上52位的有效數位。因爲規範要求小數必須是標準形式,即小數點左邊爲1,因此用52位有效數字表示了53位的 信息。其所能精確表示的整數範圍就是 2^53 ~ -2^53。
3. JS中的NaN有一點特殊:它和任何值都不相等,包括自身。
因此看到dojo庫中有這樣的equals,也是爲了讓兩個NaN可以「相等」。
function equals(a, b){ return (a === b) || ( a !== a && b !== b); }
其實前面第一條講類型時已經說過了。
5. JS中有「包裝對象」的存在,前面提到的使用簡單類型的方法其實是經過建立臨時的包裝對象,而後再使用包裝對象的方法。null和undefined沒有包裝對象,試圖引用他們的任何屬性都會拋錯。
簡單對象雖然看起來有一些屬性,好比"123".length, 可是試圖給它賦值屬性(如"123".attr = 4)會被忽略掉 ("123".attr is still undefined)。
6. JS會在必要的時候把包裝對象轉換成原始值。如「==」認爲原始值與其包裝對象相等(包裝對象會向原始值轉換),可是「===」不會進行任何轉換,因此不等。
對象原始值的比較(==)會試圖把對象的原始值求出來再比較,若是是兩個對象比較,則比較他們是否引用同一個對象。
var a = 'a', b = 'a', c = new String('a'); d = new String('a'); a == b // true
a === b // true a == c // true, 會轉換
a === c // false, 全等不轉換 c == d // false, 兩個對象的比較
c === d // false, 沒懸念
7. 對象向原始值的轉換有些複雜。顯示轉換最簡單,好比 Number("3"), Object(3)。
有一些經常使用的簡單寫法
+x //把x轉換成Number, 至關於Number(x), 也能夠寫成 x - 0,不過沒+x看起來好看 !!x //估計你們見得多了,至關於Boolean(x)
8. Object to Boolean 全部的對象類型都會轉成true。
因此別太驚訝,new Boolean(false)其實是會轉換成true。
if(new Boolean(false)) console.info("yes, new Boolean(false) is truthy");
9. Object to Number/String, 涉及到toString(), valueOf()這兩個方法,通常狀況下轉成string,toString會先調用,不行就valueOf;轉成number則順序顛倒。
10. 「-「會把它的兩個操做數都轉換成數字。而對於」+「,不少時候+的操做數會被轉換成字符串。
[1] + 1; // 」11「 [1] - 1; //0 new Date() + 1; //"Sun Aug 10 2014 00:20:41 GMT+0800 (China Standard Time)1" new Date() - 1; //1407601216775
11. 關於變量,JS中沒有塊級做用域,JS是函數做用域。因此有一種」聲明提早「的非正式稱謂(hoisting)。
實際上JS腳本雖然是解釋執行,可是在逐行執行以前還有一個」預編譯「的過程,這個過程會把context中聲明的變量放入」棧「中,並未他們賦值爲undefined,而後再開始逐條執行語句。
體會一下這個例子
a(); function a() { console.info(1);} a(); function a() {console.info(2);} a(); a = function () { console.info(3);} a(); //輸出: //2 2 2 3
12. 使用var 聲明的變量沒法被delete刪除,而做爲對象的屬性能夠。
刪除一個你本身聲明的變量確實沒有什麼必要。
(function() { var a = '123'; console.info(a); delete a; console.info(a); })(); //輸出兩個」123「
13. 做用域鏈與閉包。
這個我決定再單獨開一個坑。