我被告知必须始终在JavaScript中声明函数。真的吗?它的优点是什么?
我通常将函数分配给变量:
var foo = function() {};
但据说这是错误的,需要做一些堆栈跟踪。有人可以解释一下吗? 有人告诉我这样做:
var foo = function fooBar() {};
如果它被分配给一个对象会有意义吗?
var Foo = {};
Foo.Bar = function Bar() {};
请注意,这些功能不在全局范围内,也不是自行执行,也不是多次使用。
答案 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
。当你有一些稍微复杂的异步回调系统,事件,传递对象的方法等等时,这是特别方便的。