为什么总是在JavaScript中声明函数?

时间:2015-04-01 21:18:20

标签: javascript function

我被告知必须始终在JavaScript中声明函数。真的吗?它的优点是什么?

我通常将函数分配给变量:

var foo = function() {};

但据说这是错误的,需要做一些堆栈跟踪。有人可以解释一下吗? 有人告诉我这样做:

var foo = function fooBar() {};

如果它被分配给一个对象会有意义吗?

var Foo = {};
Foo.Bar = function Bar() {};

请注意,这些功能不在全局范围内,也不是自行执行,也不是多次使用。

1 个答案:

答案 0 :(得分:3)

首先,关于术语的一个小注释:你所拥有的不是函数声明。这是一个函数声明:

function fooBar() {
}

它创建了一个名为fooBar的函数,可通过变量fooBar访问。这是一个涉及命名函数表达式的赋值:

var foo = function fooBar() {
};

函数的名称仍为fooBar,但该函数仅绑定到函数本身内部的fooBar变量,而不是外部。但是,它确实使函数在其作用域内可访问,而不需要引用外部作用域中的变量,这意味着有两个原因可以命名它:

  • 无论外部函数中的代码如何,都能够引用自身内部的函数!

    这可以返回外部函数想要的任何内容:

    function fooBar() {
        return fooBar.toString();
    }
    
    var baz = fooBar;
    fooBar = 5;
    baz(); // "5"
    

    这始终是一致的:

    var fooBar = function fooBar() {
        return fooBar.toString();
    };
    
    var baz = fooBar;
    fooBar = 5;
    baz(); // "function fooBar() { …"
    
  • 是的,更详细的堆栈跟踪:

    function trace(func) {
        try {
            func();
        } catch (error) {
            console.log(error.stack);
        }
    }
    
    trace(function () {
        throw new Error("Bad thing");
    });
    /*
    Error: Bad thing
        at /home/ryan/test.js:10:18
        at trace (/home/ryan/test.js:3:16)
        at Object.<anonymous> (/home/ryan/test.js:9:8)
        at Module._compile (module.js:410:26)
        at Object.Module._extensions..js (module.js:428:10)
        at Module.load (module.js:335:32)
        at Function.Module._load (module.js:290:12)
        at Function.Module.runMain (module.js:451:10)
        at startup (node.js:123:18)
        at node.js:866:3
    */
    
    trace(function descriptiveName() {
        throw new Error("Bad thing");
    });
    /*
    Error: Bad thing
        at descriptiveName (/home/ryan/test.js:14:18)
        at trace (/home/ryan/test.js:3:16)
        at Object.<anonymous> (/home/ryan/test.js:13:8)
        at Module._compile (module.js:410:26)
        at Object.Module._extensions..js (module.js:428:10)
        at Module.load (module.js:335:32)
        at Function.Module._load (module.js:290:12)
        at Function.Module.runMain (module.js:451:10)
        at startup (node.js:123:18)
        at node.js:866:3
    */
    

    (Node.js如图所示。)注意第二个堆栈跟踪顶部的descriptiveName。当你有一些稍微复杂的异步回调系统,事件,传递对象的方法等等时,这是特别方便的。