首先,我想纠正 Greg: 也限定了作用域 — 名称是在遇到此定义的范围内定义的。例:function abc(){}
abc
function xyz(){
function abc(){};
// abc is defined here...
}
// ...but not here
其次,可以组合两种样式:
var xyz = function abc(){};
xyz
将像往常一样定义,在所有浏览器中都是未定义的,但Internet Explorer - 不要依赖它被定义。但它将在它的身体内定义:abc
var xyz = function abc(){
// xyz is visible here
// abc is visible here
}
// xyz is visible here
// abc is undefined here
如果要在所有浏览器上别名函数,请使用以下声明:
function abc(){};
var xyz = abc;
在本例中,两者和都是同一对象的别名:xyz
abc
console.log(xyz === abc); // prints "true"
使用组合样式的一个令人信服的理由是函数对象的“name”属性(Internet Explorer 不支持)。基本上,当您定义一个函数时,例如
function abc(){};
console.log(abc.name); // prints "abc"
其名称将自动分配。但是当你定义它像
var abc = function(){};
console.log(abc.name); // prints ""
它的名字是空的 —— 我们创建了一个匿名函数,并将其分配给某个变量。
使用组合样式的另一个很好的原因是使用一个简短的内部名称来引用自身,同时为外部用户提供一个长而无冲突的名称:
// Assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
// Let it call itself recursively:
shortcut(n - 1);
// ...
// Let it pass itself as a callback:
someFunction(shortcut);
// ...
}
在上面的示例中,我们可以对外部名称执行相同的操作,但它会太笨拙(并且速度较慢)。
(引用自身的另一种方法是使用 arguments.callee
,它仍然相对较长,在严格模式下不受支持。
在内心深处,JavaScript 以不同的方式对待这两个语句。这是一个函数声明:
function abc(){}
abc
这里定义了当前作用域中的所有内容:
// We can call it here
abc(); // Works
// Yet, it is defined down there.
function abc(){}
// We can call it again
abc(); // Works
此外,它还通过一个语句吊起:return
// We can call it here
abc(); // Works
return;
function abc(){}
这是一个函数表达式:
var xyz = function(){};
xyz
这里是从分配点定义的:
// We can't call it here
xyz(); // UNDEFINED!!!
// Now it is defined
xyz = function(){}
// We can call it here
xyz(); // works
函数声明与函数表达式是 Greg 演示的差异的真正原因。
有趣的事实:
var xyz = function abc(){};
console.log(xyz.name); // Prints "abc"
就个人而言,我更喜欢“函数表达式”声明,因为这样我就可以控制可见性。当我定义函数时,例如
var abc = function(){};
我知道我在本地定义了函数。当我定义函数时,例如
abc = function(){};
我知道我全局定义了它,前提是我没有在范围链中的任何位置定义它。这种定义风格即使在 内部使用时也是有弹性的。而定义abc
eval()
function abc(){};
取决于上下文,并可能让您猜测它实际定义的位置,特别是在 - 答案是:这取决于浏览器。eval()