14.小心命名函數表達式笨拙的做用域

相同的JavaScript函數根據上下文其含義會發生變化。bash

// 在程序的頂層做爲函數聲明
function double() { return x * 2; }
// 做爲函數表達式
var f = function double(x) { return x * 2; };
// 匿名函數表達式
var f = function(x) { return x * 2; };
複製代碼

命名函數表達式會綁定到與其相同函數名相同的變量上,該變量將做爲該函數內的一個局部變量,能夠用來寫遞歸函數表達式(命名函數表達式不能經過其內部的函數名在外部被引用)。函數

var f = function find(tree, key) {
    if (!tree) {
        return null;
    }
    if (tree.key === key) {
        return tree.value;
    }
    return find(tree, left, key) || find(tree, right, key);
}
複製代碼

使用外部做用域的函數名也可到達一樣的效果ui

var f = function(tree, key) {
    if (!tree) {
        return null;
    }
    if (tree.key === key) {
        return tree.value;
    }
    return f(tree, left, key) || f(tree, right, key);
}
複製代碼

只使用一個聲明spa

function find(tree, key) {
    if (!tree) {
        return null;
    }
    if (tree.key === key) {
        return tree.value;
    }
    return find(tree, left, key) || find(tree, right, key);
}
var f = find;
複製代碼

在ES3和有問題的JavaScript環境中命名函數表達式在其做用域內繼承了Object.prototype.constructorprototype

var construction = function() { return null; };
var f = function f() {
    return construction ();
}
f(); // {}
複製代碼

在一些JavaScript引擎中另外一個缺陷是對命名函數表達式的聲明進行提高調試

var f = function g() { return 17; };
g(); // 17
// 經過建立一個與函數表達式同名的局部變量並賦值爲null來解決
var f = function g() { return 17; };
var g = null;
複製代碼

提示

  • 在Error對象和調試器中使用命名函數表達式改進棧跟蹤。
  • 在ES3和有問題的JavaScript環境中謹記函數表達式做用域會被Object.prototype污染。
  • 謹記在錯誤百出的JavaScript環境中會提高命名函數表達式聲明,並致使命名函數表達式的重複存儲。
  • 考慮避免使用命名函數表達式或在發佈前刪除函數名。
  • 若是你將代碼發佈到正確實現的ES5環境中,那麼你沒有什麼好擔憂的。
相關文章
相關標籤/搜索