JS執行個體教程:當心JavaScript代碼陷阱

來源:互聯網
上載者:User

下面這段代碼,你知道有哪些錯誤嗎:

var g_bar = "bar";function foo(container, config) {var container = container  document,name = config.name  "無名氏",isLive = config.isLive  true;var g_bar = g_bar  "";if(g_foo) {/* your code */}}foo(document, {isLive: false});

請仔細思考後再往下閱讀。

—- 協助你思考的刷屏線 開始 —-

—- 協助你思考的刷屏線 結束 —-

1. isLive = config.isLive true, 當傳入的值有可能就是0, undefined, null, false, "", NaN這六個 falsy 值時,用 來設定預設值不妥當。更保險的做法是:

isLive = "isLive" in config ? config.isLive : true;

如果是獨立變數,可以採用:

someVar = typeof someVar !== "undefined" ? someVar : defaultValue;

注意:大部分情況下,用 已經夠用,比如:

container = container  documentname = config.name  "無名氏"

一切皆權衡。

2. var g_bar = g_bar "", 原意是取全域變數 g_bar 的值給內部變數 g_bar, 預設為空白字串。然而,實際情況等價為:

var g_bar;g_bar = g_bar  "";

很明顯, 號左邊的 g_bar 也是內部變數,並且為 undefined, 因此var g_bar = g_bar ""實際上是var g_bar = "", 沒有滿足代碼的原始意圖。

思考:代碼中的var container = container document有無問題?為什嗎?

3. if(g_foo) { /* code */ }, 這段代碼在執行時會報錯。我們都知道在 JS 裡,變數不定義就可以用。但一定要清楚,未定義的變數,僅僅是可寫,但不可讀。比如:

g_foo = 2; // 等價 window.g_foo = 2var t = g_foo2; // 不等價為 var t = window.g_foo2, 會報錯

具體原因可以參見 JavaScript 運行機制淺探:

未定義變數意味著在 scriptObject 的變數表中找不到,JS 引擎會沿著 scriptObject 的 upvalue 往上尋找,如果都沒找到,對於寫操作 i = 1; 最後就會等價為 window.i = 1; 給 window 對象新增了一個屬性。對於讀操作,如果一直追溯到全域執行環境的 scriptObject 上都找不到,就會產生運行期錯誤。

因此嚴謹的寫法是:

if(window.g_foo) {/* your code */}

不要小看這些細微之處,有時會讓人抓狂的。但這些細微之處又很容易被忽略或濫用。比如 YUI 2.8r4 裡,有一個遺傳了很久的 bug:

var NOTHING = [];// ....later: function(when, o, fn, data, periodic) {when = when  0;o = o  {};var m = fn, d = data, f, r;// ...if (d && !L.isArray(d)) {d = [data];}f = function() {m.apply(o, d  NOTHING);};// ...}

當你的調用代碼類似Lang.later(delay[0], o, "show", index)時,如果 index 不幸是 base-0 的,那麼取 0 時,m.apply(o, d NOTHING)會讓你得到“驚喜”。更妥的做法是類似 YUI3 中的修正:

// ...if (!L.isArray(d)) {d = [data];}?f = function() {m.apply(o, d);};//...

對於 和 && 的用法,很多 JS 書籍(無論中外),都用來片面強調 JS 的靈活性,包括 Douglas 的《JavaScript The Good Parts》中也存在誤導。

最後,有感於 NCZ 今天寫的 Writing Maintainable Code, 再舉一例(和本文主題關係不明顯,但的確又有關係,交給你去思考囉):

var isBoy = true;isBoy = typeof isGirl !== "undefined" ? !isGirl : true;

或者來個耍酷的代碼:

var isBoy = true;(typeof isGirl !== "undefined") && (isBoy =  !isGirl);

然而,以上兩種寫法,無論從代碼長度還是效能上講,都不如更直白的寫法:

var isBoy = true;if(typeof isGirl !== "undefined") isBoy =  !isGirl;

簡單質樸,往往是最好的。



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.