下面這段代碼,你知道有哪些錯誤嗎:
請仔細思考後再往下閱讀。
—- 幫助你思考的刷屏線 開始 —-
—- 幫助你思考的刷屏線 結束 —-
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 || document
name = 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 = 2
var 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;
簡單質樸,往往是最好的。
轉自:http://lifesinger.org/blog/2009/12/easy-ignorable-js-code/