數據類型和定義javascript
JavaScript衆多類型中有個Null類型,它有個惟一的值null, 即它的字面量,定義爲徹底沒有任何意義的值。其表現得像個對象,以下檢測代碼:java
以下截圖:正則表達式
儘管typeof值顯示是"object",但null並不認爲是一個對象實例。要知道,JavaScript中的值都是對象實例,每一個數值都 是Number對象,每一個對象都是Object對象。由於null是沒有值的,因此,很明顯,null不是任何東西的實例。所以,下面的值等於 false。數組
譯者注:null還有被理解爲對象佔位符一說瀏覽器
NaN本意是表示某個值不是數值,可是其自己卻又是數值,且不等於其自身,很奇怪吧,看下面的代碼:閉包
結果以下截圖:
app
實際上NaN不等於任何東西。要確認某玩意是否是NaN只能使用isNaN.函數
下面是JavaScript另外一個極品怪癖:測試
結果以下截圖:
this
想要知道這裏發生了什麼,你須要理解truthy和falsy這個概念。它們是一種true/flase字面量。在JavaScript中,所 有的非Boolean型值都會內置一個boolean標誌,當這個值被要求有boolean行爲的時候,這個內置布爾值就會出現,例如當你要跟 Boolean型值比對的時候。
由於蘋果不能和梨作比較,因此當JavaScript兩個不一樣類型的值要求作比較的時候,它首先會將其弱化成相同的類型。false, undefined, null, 0, "", NaN都弱化成false。這種強制轉化並非一直存在的,只有看成爲表達式使用的時候。看下面這個簡單的例子:
結果以下截圖:
上面測試中,咱們試圖將數值0和boolean值false作比較,因二者的數據類型不兼容,JavaScript自動強制轉換成統一的等同的truthy和falsy,其中0等同於false(正如上面所說起的)。
你可能注意到了,上面一些等同false的值中並無空數組。只因空數組是個怪胚子:其自己實際上屬於truthy,可是當空數組與Boolean型作比較的時候,其行爲表現又屬於falsy。不解?這是由緣由的。先舉個例子驗證下空數組的奇怪脾氣:
結果以下截圖,連續彈出兩個框框:
譯者注:之因此會有這種差別,根據做者的說法,數組內置toString()方法,例如直接alert的時候,會以join(「,」)的形式彈 出字符串,空數組天然就是空字符串,因而等同false。具體可參見做者另一篇文章,《Twisted logic: understanding truthy & falsy》。不過我我的奇怪的是,像空對象,空函數,弱等於true或者false的時候都顯示false,爲什麼?真的由於數組是個怪胎,須要特殊考慮 嗎?
爲避免強制轉換在比較方面的問題,你可使用強等於(===)代替弱等於(==)。
結果以下截圖(win7 FF4):
若是你想深刻探究JavaScript中類型強制轉換等些特有的癖好,能夠參見官方相關的文檔規範:section 11.9.3 of the ECMA-262
這是JavaScript最不爲人知的祕密之一,v1.3中首次引入。大部分狀況下,replace()的使用相似下面:
這是一個簡單的替換,一個字符串,一個星號。可是,若是咱們但願在替換髮生的時候有更多的控制,該怎麼辦呢?咱們只但願替換30如下的數值,該怎麼辦呢?此時若是僅僅依靠正則表達式是鞭長莫及的。咱們須要藉助回調函數的東風對每一個匹配進行處理。
當每一個匹配完成的時候,JavaScript應用回調函數,傳遞匹配內容給match參數。而後,根據回調函數裏面的過濾規則,要麼返回星號,要麼返回匹配自己(無替換髮生)。
以下截圖:
很多javascript工程師都是隻經過match和replace和正則表達式打交道。但JavaScript所定義的正則表達式相關方法遠不止這兩個。
其中值得一提的是test(),其工做方式相似match(),可是返回值卻不同:test()返回的是布爾型,用來驗證是否匹配,執行速度高於match()。
上面行代碼用來驗證字符串是否有三個以上普通字符,顯然"hello"是符合要求的,因此彈出true。
結果以下截圖:
咱們還應注意RegExp對象,你能夠用此建立動態正則表達式對象,例如:
這兒,咱們基於參數word動態建立了匹配驗證。這段測試代碼做用是不區分大小選的狀況下選擇car這個單詞。眼睛一掃而過,測試英文句子中只有一個單詞是car,所以這裏的演出僅一個單詞。\b是用來表示單詞邊界的。
結果以下截圖:
做用域這玩意是用來決定什麼變量是可用的,獨立的JavaScript(如JavaScript不是運行中函數中)在window對象的全局做用域下操做,window對象在任何狀況下均可以訪問。然而函數中聲明的局部變量只能在該函數中使用。
這兒咱們的變量和函數都聲明在全局做用域中。由於this指向當前做用域,在這個例子中就是window。所以,該函數尋找 window.animal,也就是'dog'了。到目前爲止,一切正常。然而,實際上,咱們可讓函數運行在不一樣的做用域下,而忽視其自己的做用域。我 們能夠用一個內置的稱爲call()的方法來實現做用域的冒充。
call()方法中的第一個參數能夠冒充函數中的this,所以,這裏的this.animal實際上就是myObj.animal,也就是'camel'了。後面的參數就做爲普通參數傳給函數體。
另一個與之相關的是apply()方法,其做用於call()同樣,不一樣之處在於,傳遞給函數的參數是以數組形式表示的,而不是獨立的變量們。因此,上面的測試代碼若是用apply()表示就是:
demo頁面中,點擊第一個按鈕的結果以下截圖:
點擊第二個和第三個按鈕的結果以下:
下面這個是很OK的:
這裏的解析足夠簡單:聲明一個函數,而後由於()解析當即執行它。你可能會奇怪爲什麼要這麼作(指直接屁股後面()調用),這看上去是有點自相矛盾的:函數包含的一般是咱們想稍後執行的代碼,而不是當下解析即執行的,不然,咱們就沒有必要把代碼放在函數中。
另一個執行函數自身(self-executing functions (SEFs))的不錯使用是爲在延遲代碼中使用綁定變量值,例如事件的回調(callback),超時執行(timeouts)和間隔執行(intervals)。以下例子:
Newbies在論壇裏總問這裏timeout的彈出爲何是goodbye而不是hello?答案就timeout中的回調函數直到其運行的時候纔去賦值someVar變量的值。而那個時候,someVar已經被goodbye重寫了好長時間了。
SEFs提供了一個解決此問題的方法。不是像上面同樣含蓄地指定timeout回調,而是直接將someVar值以參數的形式傳進去。效果顯著,這意味着咱們傳入並孤立了someVar值,保護其不管後面是地震海嘯仍是女友發飆咆哮都不會改變。
風水輪流轉,此次,這裏的彈出就是hello了。這就是函數參數和外部變量的點差異了哈。
例如,最後一個按鈕點擊後的彈出以下:
直到如今我都沒有真正理解爲什麼Mozilla會這樣子。爲了有個清晰的認識,看下面這個例子:
大部分瀏覽器彈出的結果是ff9900,而FireFox的結果倒是rgb(255, 153, 0),RGB的形式。常常,處理顏色的時候,咱們須要花費很多代碼將RGB顏色轉爲Hex。
下面是上面代碼在不一樣瀏覽器下的結果:
這個古怪的問題不僅會出如今JavaScript中,這是計算機科學中一個廣泛存在的問題,影響了不少的語言。標題等式輸出的結果是0.30000000000000004。
這是個被稱爲機器精度的問題。當JavaScript嘗試執行(0.1 + 0.2)這行代碼的時候,會把值轉換成它們喜歡的二進制口味。這就是問題的起源,0.1實際上並非0.1,而是其二進制形式。從本質上將,當你寫下這些 值的時候,它們註定要失去精度。你可能只是但願獲得個簡單的兩位小數,但你獲得的(根據Chris Pine的註解)是二進制浮點計算。比如你想把一段應該翻譯成中文簡體,結果出來的倒是繁體,其中仍是有差別是不同的。
通常處理與此相關的問題有兩個作法:
例如,咱們不該該下面這樣:
而能夠試試這樣:
咱們以一個和風細雨的小古怪結束。聽起來可能有點奇怪,undefined並非JavaScript中的保留字,儘管它有特殊的意義,而且是惟一的方法肯定變量是否未定義。所以:
目前爲止,一切看上去風平浪靜,正常無比,但劇情老是很狗血:
這就是爲何jQuery源碼中最外部的閉包函數要有個並無傳入的undefined參數,目的就是保護undefined不要被外部的些不良乘虛而入。