(五)我的JavaScript系列:JavaScript的糟粕


淚眼問花花不語,亂紅飛過秋千去。

JavaScript的糟粕

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

全局變量

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

  1. 在函數外通過var定義:

    var foo = value;

  2. 綁定到全局對象window:

    window.foo = value;

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

    foo = value;

這里的准則就是一般不要在函數外定義變量(即便是通過var),定義變量時一定不能忘記var(但忘記var又是件很常見的錯誤)。

作用域

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學習教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM