本系列主要記錄javascript中,新手比較容易搞錯的地方。 (1)要特別註意相等運算符==。JavaScript在設計時,有兩種比較運算符:第一種是==比較,它會自動轉換數據類型再比較,很多時候,會得到非常詭異的結果;第二種是 比較,它不會自動轉換數據類型,如果數據類型不一致,返回false,如 ...
本系列主要記錄javascript中,新手比較容易搞錯的地方。
(1)要特別註意相等運算符==
。JavaScript在設計時,有兩種比較運算符:第一種是==
比較,它會自動轉換數據類型再比較,很多時候,會得到非常詭異的結果;第二種是===
比較,它不會自動轉換數據類型,如果數據類型不一致,返回false
,如果一致,再比較。由於JavaScript這個設計缺陷,不要使用==
比較,始終堅持使用===
比較。
(2)NaN
這個特殊的Number與所有其他值都不相等,包括它自己:
NaN === NaN; // false
唯一能判斷NaN
的方法是通過isNaN()
函數:
isNaN(NaN); // true
(3)註意浮點數的相等比較:
1 / 3 === (1 - 2 / 3); // false
這不是JavaScript的設計缺陷。浮點數在運算過程中會產生誤差,因為電腦無法精確表示無限迴圈小數。要比較兩個浮點數是否相等,只能計算它們之差的絕對值,看是否小於某個閾值:
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true
(4)null和undefined
null表示一個“空”的值,它和0以及空字元串''不同,0是一個數值,''表示長度為0的字元串,而null表示“空”。
在其他語言中,也有類似JavaScript的null的表示,例如Java也用null,Swift用nil,Python用None表示。但是,在JavaScript中,還有一個和null類似的undefined,它表示“未定義”。
JavaScript的設計者希望用null表示一個空的值,而undefined表示值未定義。事實證明,這並沒有什麼卵用,區分兩者的意義不大。大多數情況下,我們都應該用null。undefined僅僅在
判斷函數參數是否傳遞的情況下有用。
(5)變數的聲明
JavaScript在設計之初,為了方便初學者學習,並不強制要求用var申明變數。這個設計錯誤帶來了嚴重的後果:如果一個變數沒有通過var申明就被使用,那麼該變數就自動被申明
為全局變數:
i = 10; // i現在是全局變數
在同一個頁面的不同的JavaScript文件中,如果都不用var申明,恰好都使用了變數i,將造成變數i互相影響,產生難以調試的錯誤結果。
使用var申明的變數則不是全局變數,它的範圍被限制在該變數被申明的函數體內(函數的概念將稍後講解),同名變數在不同的函數體內互不衝突。
為了修補JavaScript這一嚴重設計缺陷,ECMA在後續規範中推出了strict模式,在strict模式下運行的JavaScript代碼,強制通過var申明變數,未使用var申明變數就使用的,將導致
運行錯誤。
啟用strict模式的方法是在JavaScript代碼的第一行寫上:
'use strict';
這是一個字元串,不支持strict模式的瀏覽器會把它當做一個字元串語句執行,支持strict模式的瀏覽器將開啟strict模式運行JavaScript。
(6)變數的賦值
在JavaScript中,使用等號=對變數進行賦值。可以把任意數據類型賦值給變數,同一個變數可以反覆賦值,而且可以是不同類型的變數,但是要註意只能用var申明一次,例如:
var a = 123; // a的值是整數123
a = 'ABC'; // a變為字元串
這種變數本身類型不固定的語言稱之為動態語言,與之對應的是靜態語言。靜態語言在定義變數時必須指定變數類型,如果賦值的時候類型不匹配,就會報錯。例如Java是靜態語言,
賦值語句如下:
int a = 123; // a是整數類型變數,類型用int申明
a = "ABC"; // 錯誤:不能把字元串賦給整型變數
和靜態語言相比,動態語言更靈活,就是這個原因。
(7)模板字元串
要把多個字元串連接起來,可以用+號連接:
var name = '小明';
var age = 20;
var message = '你好, ' + name + ', 你今年' + age + '歲了!';
alert(message);
如果有很多變數需要連接,用+號就比較麻煩。ES6新增了一種模板字元串,表示方法和上面的多行字元串一樣,但是它會自動替換字元串中的變數:
var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}歲了!`;
alert(message);
(8)字元串操作
字元串是不可變的,如果對字元串的某個索引賦值,不會有任何錯誤,但是,也沒有任何效果:
var s = 'Test';
s[0] = 'X';
alert(s); // s仍然為'Test'
JavaScript為字元串提供了一些常用方法,註意,調用這些方法本身不會改變原有字元串的內容,而是返回一個新字元串。
(9)字元串索引計算位置
indexOf
indexOf()會搜索指定字元串出現的位置:
var s = 'hello, world';
s.indexOf('world'); // 返回7,計算這個值的時候,從1開始計算,數到該單詞第一個字元出現的位置!
s.indexOf('World'); // 沒有找到指定的子串,返回-1
substring
substring()返回指定索引區間的子串:
var s = 'hello,world'
s.substring(0, 5); // 從索引0開始到5(不包括5),返回'hello'
s.substring(6); // 從索引6開始到結束(包括6),返回'world'
計算這個索引的時候,記著substring的左數值要包括,右數值不包括。
(10)數組
JavaScript的Array可以包含任意數據類型,並通過索引來訪問每個元素。
要取得Array的長度,直接訪問length屬性:
var arr = [1, 2, 3.14, 'Hello', null, true];
arr.length; // 6
請註意,直接給Array的length賦一個新的值會導致Array大小的變化:
var arr = [1, 2, 3];
arr.length; // 3
arr.length = 6;
arr; // arr變為[1, 2, 3, undefined, undefined, undefined]
arr.length = 2;
arr; // arr變為[1, 2]
Array可以通過索引把對應的元素修改為新的值,因此,對Array的索引進行賦值會直接修改這個Array:
var arr = ['A', 'B', 'C'];
arr[1] = 99;
arr; // arr現在變為['A', 99, 'C']
請註意,如果通過索引賦值時,索引超過了範圍,同樣會引起Array大小的變化:
var arr = [1, 2, 3];
arr[5] = 'x';
arr; // arr變為[1, 2, 3, undefined, undefined, 'x']
大多數其他編程語言不允許直接改變數組的大小,越界訪問索引會報錯。然而,JavaScript的Array卻不會有任何錯誤。在編寫代碼時,不建議直接修改Array的大小,
訪問索引時要確保索引不會越界。
註:本文素材皆來自廖大神的個人網站,我只是做一個簡要的總結。在此對他表示感謝,給大家提供這樣的一個平臺。出處:http://www.liaoxuefeng.com/