2011/08/25

javascript中的null與undefined的差異

有些時候會作 object detection 來判斷物件是否存在(像是在 function 內判斷傳進來的參數存在與否),而判斷的標準用 null 或 undefined 其實會有些微的不同。
ECMA-262標準(*註1)中關於這部份的敘述:
  • undefined value

    primitive value used when a variable has not been assigned a value.
  • null value

    primitive value that represents the intentional absence of any object value.
簡單說,null 表示無值,而 undefined 表示沒有定義的變數。
下面就分別對其做了一些測試:

null
雖然 type 是 objet,null 但不算一個真正的物件,不是空字串'',也不是 false 值,但如果直接當成條件式來判斷,會得到 false
alert(null); //null
alert(typeof null); //object
alert(null == ''); //false
alert(null == false); //false
alert(null instanceof Object); //false
alert(null ? true: false); //false
理所當然的也不能對 null 的屬性作操作
var nullObj = null;
nullObj.property = 'value'; //丟出TypeError
alert(nullObj.someProperty) //丟出TypeError

undefined
undefined 的 type 就是 undefined,當成條件式使用一樣會得到 false
alert(typeof undefined); //undefined
alert(undefined == ''); //false
alert(undefined == false); //false
alert(undefined instanceof Object); //false
alert(undefined ? true: false); //false
沒宣告過的變數,雖然 type 是 undefined,但存取它則會丟出 ReferenceError
alert(typeof undefinedObj); //undefined
alert(undefinedObj); //丟出ReferenceError
alert(undefinedObj.property); //丟出ReferenceError
alert(undefinedObj === undefined); //丟出ReferenceError
宣告卻沒給值的變數,預設會給它 undefined 的值
var undefinedObj;
alert(typeof undefinedObj); //undefined
alert(undefinedObj); //undefined
alert(undefinedObj.property); //丟出ReferenceError
alert(undefinedObj === undefined); //true
定義過的物件,屬性未定義(宣告)前都屬於"宣告卻沒給值的變數",也就是帶 undefined 值
var definedObj = new Object();
alert(typeof definedObj.property) //undefined
alert(definedObj.property); //undefined
alert(definedObj.property === undefined); //true
從 function 內接收的參數如果有宣告且呼叫時未傳入值,等同宣告卻沒給值的變數
function methodCall(parameter) {
 alert(typeof parameter); //undefined
 alert(parameter); //undefined
}
methodCall();
微妙的是,用 == 運算子做比較,null 跟 undefined 會得到 true
alert(null == undefined) //true
alert(null === undefined); //false

結論
null 跟 undefined 就像 true/false 一樣表示一個值;而用於 object detection 的時候,遇到一個不知道宣告與否的變數,用 typeof 來判斷比較好。因為除非你自己設 null 值,不然在程式中遇到的機率很低。(目前我只知道 document.getElementById() 如果找不到元素,會回傳 null)
//如果用其他運算子來判斷,遇到未宣告過的變數會直接丟error
if(typeof obj == 'undefined') {
 //do something here...
}

//真的擔心會遇到null值,可以再加上後面的判斷式
if(typeof obj == 'undefined' && obj) {
 //do something here...
}
對於已宣告的物件,則可以直接當成條件式來使用
var definedObj = new Object();
//javascript中&&和||只要運算到可以得出結果就會忽略剩下的運算式
//所以如果otherObj無定義,則直接跳出此if判斷
if(definedObj.otherObj && definedObj.otherObj.someFunction) {
 definedObj.otherObj.someFunction();
}

//函式呼叫
function methodCall(parameter) {
 if(parameter) {
  //do something with parameter...
 }
}

註1:ECMA-262 是 javascript 的標準,由 ECMA 這個組織定的

沒有留言:

張貼留言