(五)個人JavaScript系列:JavaScript的糟粕

淚眼問花花不語,亂紅飛過鞦韆去。javascript

JavaScript的糟粕

JavaScript語言是一門集精華與糟粕於一體的語言。在JavaScript: the good parts中,便集中討論了關於精華與糟粕的主題。有興趣的同窗能夠讀讀這本書,真的不錯。基礎不錯的能夠跳過前面的章節,直接進入附錄的糟粕雞肋的部分。我呢,就先在這本書裏列舉幾個我感興趣的糟粕部分與你們分享:java

全局變量

這恐怕是JavaScript當中最坑的部分了。先且不論全局變量的種種壞處了。在JavaScript中,定義一個全局變量是很輕鬆的一件事,能夠經過下面的三種方式:編程

  1. 在函數外經過var定義:閉包

    var foo = value;函數

  2. 綁定到全局對象window:學習

    window.foo = value;this

  3. 在任何地方不經過var定義變量:.net

    foo = value;prototype

這裏的準則就是通常不要在函數外定義變量(即使是經過var),定義變量時必定不能忘記var(但忘記var又是件很常見的錯誤)。code

做用域

JavaScript中的只有全局做用域和函數做用域兩種,沒有塊做用域。同一個函數內的全部變量屬於同一個做用域。例以下面的代碼,foo的做用域不是if塊,而是函數foo,因此在if塊以外依然能夠訪問foo。

function f() {
  if(true) {
     var foo = 'foo';
  }
  console.log(foo); //依然能夠訪問foo
}

因此一種推薦的方式是在函數的頂部聲明變量,就像C語言那樣作。整個函數看上去就像下面的形式:

function f() {
  var a, b, c; //在函數頂部聲明函數內使用的全部變量

  a = b = c = 2; //而後再使用變量
}

不過,像這樣編程是一種很煩的方式。

自動插入分號機制

JavaScript會在每行末尾自動插入一個分號,只要語法容許。例以下面的代碼

return
{ 
   status: true
};

會被轉化爲:

return;
{ 
   status: true
};

但下面的代碼卻不會(由於插入分號語法上不容許):

return {
   status: true
}

因此爲了不理解上的歧義,JavaScript最佳實踐建議手動加上分號,而不要依賴語言的自動插入分號機制。不過,現代語言(Ruby、Python等)基本都去掉分號行爲了,每行代碼都要加上個分號也是個煩人的事。

保留字

JavaScript上定義了不少但壓根沒用上的保留字,例如:abstract, boolean, byte, int

typeof

JavaScript的typeof每每文不對題,例如:

typeof null === 'object'

因此,用到typeof時,每每要多加當心。

浮點數

JavaScript中的數字沒有整數類型,只有浮點數類型(實際爲IEEE 754,即C語言的double類型)。衆所周知,浮點數獲得的結果是不精確的。不過好在浮點數表示的整數,它們之間的運算是精確的。

False值

JavaScript中,有不少值可以表示假值:

  1. 0
  2. NaN (非數)
  3. ‘’ (空字符串)
  4. false
  5. null
  6. undefined

因此,在使用if條件判斷的時候,要適當注意下。

==

在JavaScript中,有兩種形式的等號操做符:=====。其中==存在坑的地方。它在比較前,會先嚐試進行類型轉化再去比較。這裏的問題在於,類型轉化的規則太過複雜了,很難掌握。例如

'' == '0'    //false 
0 == ''      //true
0 == '0'    //true

===在比較的時候不會進行類型轉化,只有類型相同和值相等的兩個對象纔會返回true。

缺乏塊符號的語句

塊符號,即{}。在JavaScript中,ifwhilefor內部的語句須要用大括號括起來。例外的狀況是它們下面只有一條語句的時候。

if(ok)
  t = true;

不過這不是建議的方式。JavaScript最佳實踐要求不管何種狀況都要加上大括號,除非它們寫在同一行。要麼

if(ok) {
  t = true;
}

要麼

if(ok) t = true;

第二種明顯不怎麼易看。

new語句

JavaScript的構造器函數須要經過new新建對象。若是忘記new,那它就是一個普通的函數調用,this被綁定到全局對象window。此時是很是危險的。

function Dog(name) {
  this.name = name;
}

Dog.prototype.bark = function() {
  return 'I am ' + this.name;
}

當調用構造器函數時,千萬別漏掉new。JavaScript最佳實踐甚至建議不要使用構造器函數,也就是不要經過new來新建對象。它的意思大概是像下面這樣新建對象:

function dog(name) {
  var dog = {};
  dog.bark = function() {
     return 'I am ' + name;
  }
  return dog;
}

這是我之前常常用的一種方式。這裏利用閉包的特性將name化爲私有變量。一個很明顯的缺點是bark函數被定義了屢次。

就該被遺忘的特性

下面的一些特性我歷來沒接觸過,聽說是坑人的特性。既然這樣,我也不要去學習它們了。你們直接忽略它們就能夠了。

  1. with語句
  2. eval函數
  3. ++ -- (不要a++,用a+=1替代)
  4. 位運算符 (& | ^ ~ >> <<)

相關資源

一些推薦的JavaScript學習教程

相關文章
相關標籤/搜索