JavaScript 運算式中的 undefined

此篇文章最近更新時間為2012-08-14 21:28:12 目前共有7篇留言

關於作者 - JosephJ

任職於 Faria。喜好戶外運動、2008 年 5 月完成「跑步環島」。對於新技術跟程式碼有著強烈的偏執狂。

每次在寫 JavaScript 幾乎都會碰到 undefined 的處理,只是一直沒有花時間去看其中的細節,昨天終於搞懂中間的眉角了 :D

常用 typeof 檢查 undefined 的變數

在 JavaScript 中,我常會運算式中用 typeof 來確定一個變數是否已經被 Assign 值:

if (typeof(url) !== "undefined") { }

這已經變成一種習慣,「印象中」若不這樣處理、未定義的變數就會造成 JavaScript 錯誤 (Uncaught ReferenceError)。

用 Logical OR 來指定參數的預設值

邏輯運算子的 OR (Logical OR) 、我常用來指定函式中參數的預設值。例如下面的 url 與 callback:

var foo = function (url, callback) { url = url || "http://www.miiicasa.com/"; callback = callback || function () {}; }; foo(); // url 跟 callback 都將會是 undefined

url 與 callback 此時都是 undefined,但程式卻可以順利運作。

為什麼 undefined 有時有錯誤、有時沒錯誤?

為什麼第一個範例不能直接將 undefined 當成 false、但第二個範例卻可以? 翻了 Nicholas ZakasProfessional JavaScript for Web Developer, 裡面在布林值運算子(Boolean Operator)中的 Logical NOT、Logical AND、Logical OR 都有提到:"If either operand is undefined, an error occurs."(只要有任何運算元是 undefined 的話就會造成 JavaScript Error)。不過這一點似乎沒辦法解釋第二個例子,即使在沒給參數的情況下都不會有錯誤。

實際寫了幾行程式來試試看吧!先試試看 Logical AND:

var foo = (unknown && true); // JavaScript Error!

當 unknown 在未宣告的前提下、的確會引發 JavaScript Error、Logical OR 同樣也會有問題:

alert(typeof(someUrl)); // undefined //alert(someUrl == null); // 會造成 JS Error var url = someUrl || "http://www.miiicasa.com/" // JavaScript Error!

那若是先宣告但不 Assign 值呢?

var someUrl; alert(typeof(someUrl)); // 此時 unknown 依然為 undefined alert(someUrl == null); // 此時 unknown 與 null 變成相等的! var url = someUrl || "http://www.miiicasa.com/" // 驚!不會有錯誤!

See ? someUrl 即使宣告了一樣是 undefined、但卻可以不會讓 JavaScript 發生錯誤。 實在很奇妙,可以簡單下個註解:對於已宣告但還沒 Assign 值的變數、可被當做 null 來處理。 開發流程若整合了 JSLint、應該不會有未宣告的變數存在。 回到上面的第一個例子,我其實是沒必要使用 typeof 來避免錯誤的,可以改為:

var url; if (!url) { }

搞清楚這個關係後,程式碼就可以少打一點啦 :D 也用了 "use strict"; 做測試,行為也是一致無誤的。



Comments

  1. fin 2013-06-05 17:16:34
    個人理解是這樣
    undefined分成兩種,一種是變數未被宣告,一種是變數值為undefined

    會出現問題的都是第一種,找不到此變數,拿不到他的值,自然就GG
    alert(someUrl); 會掛掉就是因為根本找不到這個變數

    另外有一種狀況比如我有一個空物件obj = {};
    可以知道 obj.a === undefined
    但alert(obj.a) 是不會拋出錯誤的
    因為雖然a不是obj的變數,但是透過存在的物件obj存取,回傳給你的值是undefined,我們還是有取得一個'undefined'的值,故不會有錯誤。
  2. niles 2012-10-18 19:48:45
    啊呜不愧是YUI传道士,对JS的研究始终孜孜不倦 :D
    之前你提出的Javascript 模块化开发一直都有使用,我还把这种思路用在了Prototype和Jquery上,并做了一些改造,表现都非常好,但有一点我一直都找不到解决方案,就是如果页面中有iframe,如何让iframe页面中的模块也能相互listen
  3. josephj 2012-10-06 10:11:30
    謝謝支持啊!
    講義都已經放在 http://speakerdeck.com/u/josephj 上面了 :)
  4. 陳雪亞 2012-09-14 09:57:08
    你好,我是9月9號在中國軟件開發者大會中聽課的同學O(∩_∩)O哈哈~

    對你講的課程很感興趣,不知道方不方便把你講課的資料發給我呢!

    萬分感謝!叩拜~~~~~ (*^__^*) 嘻嘻……
  5. janpoem 2012-09-03 20:48:17
    说得好啊!虽然是很浅显的道理,但却是骨灰级才会意识到这个问题的严重性。其实这些都属于写JS应该掌握的代码习惯,而且还有很多。
  6. othree 2012-08-22 23:14:10
    我之前測試是只有查到 global scope 時,還是真的找不到變數的那種 undefined 才會有錯誤,如果已經是宣告過的那就不會有錯誤了,即使它的值是 undefined ,所以基本上要注意的就只有要宣告在最外層的 namespace 變數才是吧
  7. dilettanteman 2012-08-16 09:05:13
    已宣告但還沒 assign 值的變數是 undefined
    (undefined == null) 結果為 true 是因為兩種都是 false value
    如果使用 (undefined === null) 結果就是 false
    文章中的紅字部份我覺得會容易讓人誤導成已宣告但還沒 assign 值的變數會是 null 而不是 undefined

    ps. 程式碼的部份如果排版好一點會容易看一點 ...
暱稱: 必填。
Email: 非必填。若填寫為不公開欄位,僅供站長參考聯繫。
內容: 必填。限 255 個字元以內。
驗證碼:
送出

Facebook Comment