JavaScript 常見錯誤
本章指出一些常見的 JavaScript 錯誤。
意外使用賦值運算符
如果程序員在 if
語句中意外使用賦值運算符(=
)而不是比較運算符(===
),JavaScript 程序可能會產生一些無法預料的結果。
這條 if
語句返回 false
(正如預期),因為 x 不等于 10:
var x = 0; if (x == 10)
這條 if
語句返回 true
(也許不像預期),因為 10 為 true:
var x = 0; if (x = 10)
這條 if
語句返回 false
(也許不像預期),因為 0 為 false:
var x = 0; if (x = 0)
賦值總是返回賦值的值。
期望松散的比較
在常規比較中,數據類型不重要。這條 if
語句返回 true
:
var x = 10; var y = "10"; if (x == y)
在嚴格比較中,數據類型確實重要。這條 if
語句返回 false
:
var x = 10; var y = "10"; if (x === y)
有一個常見的錯誤是忘記在 switch
語句中使用嚴格比較:
這條 switch
語句會顯示提示框:
var x = 10; switch(x) { case 10: alert("Hello"); }
這條 switch
語句不會顯示提示框:
var x = 10; switch(x) { case "10": alert("Hello"); }
令人困惑的加法和級聯
加法用于加數值。
級聯(Concatenation)用于加字符串。
在 JavaScript 中,這兩種運算均使用相同的 +
運算符。
正因如此,將數字作為數值相加,與將數字作為字符串相加,將產生不同的結果:
var x = 10 + 5; // x 中的結果是 15 var x = 10 + "5"; // x 中的結果是 "105"
如果是兩個變量相加,很難預測結果:
var x = 10; var y = 5; var z = x + y; // z 中的結果是 15 var x = 10; var y = "5"; var z = x + y; // z 中的結果是 "105"
令人誤解的浮點
JavaScript 中的數字均保存為 64 位的浮點數(Floats)。
所有編程語言,包括 JavaScript,都存在處理浮點值的困難:
var x = 0.1; var y = 0.2; var z = x + y // z 中的結果并不是 0.3
為了解決上面的問題,請使用乘除運算:
實例
var z = (x * 10 + y * 10) / 10; // z 中的結果將是 0.3
對 JavaScript 字符串換行
JavaScript 允許您把一條語句換行為兩行:
例子 1
var x = "Hello World!";
但是,在字符串中間來換行是不對的:
例子 2
var x = "Hello World!";
如果必須在字符串中換行,則必須使用反斜杠:
例子 3
var x = "Hello \ World!";
對 return 語句進行換行
在一行的結尾自動關閉語句是默認的 JavaScript 行為。
正因如此,下面兩個例子返回相同的結果:
例子 1
function myFunction(a) { var power = 10 return a * power }
例子 2
function myFunction(a) { var power = 10; return a * power; }
JavaScript 也允許您將一條語句換行為兩行。
正因如此,例子 3 也將返回相同的結果:
例子 3
function myFunction(a) { var power = 10; return a * power; }
但是,如果把 return
語句換行為兩行會發生什么呢:
例子 4
function myFunction(a) { var power = 10; return a * power; }
此函數將返回 undefined
!
為什么呢?因為 JavaScript 認為你的意思是:
例子 5
function myFunction(a) { var power = 10; return; a * power; }
解釋
如果某條語句是不完整的:
var
JavaScript 將通過讀取下一行來完成這條語句:
power = 10;
但是由于這條語句是完整的:
return
JavaScript 會自動關閉該語句:
return;
發生這種情況是因為,在 JavaScript 中,用分號來關閉(結束)語句是可選的。
JavaScript 會在行末關閉 return
語句,因為它本身就是一條完整的語句。
所以,絕不要對 return
語句進行換行。
通過命名索引來訪問數組
很多編程語言支持帶有命名索引的數組。
帶有命名索引的數組被稱為關聯數組(或散列)。
JavaScript 不支持帶有命名索引的數組。
在 JavaScript 中,數組使用數字索引:
實例
var person = []; person[0] = "Bill"; person[1] = "Gates"; person[2] = 46; var x = person.length; // person.length 將返回 3 var y = person[0]; // person[0] 將返回 "Bill"
在 JavaScript 中,對象使用命名索引。
如果您使用命名索引,那么在訪問數組時,JavaScript 會將數組重新定義為標準對象。
在自動重定義之后,數組方法或屬性將產生未定義或非正確的結果:
實例
var person = []; person["firstName"] = "Bill"; person["lastName"] = "Gates"; person["age"] = 46; var x = person.length; // person.length 將返回 0 var y = person[0]; // person[0] 將返回 undefined
用逗號來結束定義
對象和數組定義中的尾隨逗號在 ECMAScript 5 中是合法的。
對象實例:
person = {firstName:"Bill", lastName:"Gates", age:62,}
數組實例:
points = [35, 450, 2, 7, 30, 16,];
警告!!
Internet Explorer 8 會崩潰。
JSON 不允許尾隨逗號。
JSON:
person = {firstName:"Bill", lastName:"Gates", age:62}
JSON:
points = [35, 450, 2, 7, 30, 16];
Undefined 不是 Null
JavaScript 對象、變量、屬性和方法可以是未定義的。
此外,空的 JavaScript 對象的值可以為 null
。
這可能會使測試對象是否為空變得有點困難。
您可以通過測試類型是否為 undefined
,來測試對象是否存在:
實例
if (typeof myObj === "undefined")
但是您無法測試對象是否為 null
,因為如果對象未定義,將拋出錯誤:
不正確的:
if (myObj === null)
要解決此問題,必須測試對象是否為 null
,而不是未定義。
但這仍然會引發錯誤:
不正確的:
if (myObj !== null && typeof myObj !== "undefined")
因此,在測試非 null 之前,必須先測試未定義:
正確的:
if (typeof myObj !== "undefined" && myObj !== null)
期望塊級范圍
JavaScript 不會為每個代碼塊創建新的作用域。
很多編程語言都是如此,但是 JavaScript 并非如此。
認為這段代碼會返回 undefined
,是新的 JavaScript 開發者的常見錯誤:
實例
for (var i = 0; i < 10; i++) { // 代碼塊 } return i;