可能重复:
JavaScript: var functionName = function() {} vs function functionName() {}
What is the difference between a function expression vs declaration in Javascript?
我知道函数声明和表达式之间的区别,但是遇到了涉及函数名称的代码,并希望了解运行它时会发生什么:
var abc = function def() {
console.log("Wait! What??");
}
我知道这不是JavaScript的一种方式,只是想知道一些事情:
abc
会怎样?为什么会这样?可以调用abc
但不是def
,为什么?def
是undefined
- 为什么?如果它应该是,那里
内存泄漏?abc.prototype
是函数def
?由于
答案 0 :(得分:8)
abc会怎么样?
它包含一个函数对象。如果你什么都不做,它将被垃圾收集。
为什么会这样?
为什么不呢?什么“有用”?
可以调用abc而不是def,为什么?
这只适用于外部,而不是IE。见下文。
是函数声明还是表达式?
这是一个函数表达式。您可以很容易地看到它,因为它是赋值表达式的一部分;声明总是需要在顶层(函数或全局代码)
def未定义 - 为什么?
仅限外界。函数表达式不会创建变量。 “def”是函数的name,函数内部也是函数的引用。这允许递归,例如不使用任何外部变量。
var abc = function def() {
def === abc; // true
def.name; // "def"
}
abc();
def; // undefined
如果它应该是,是否有内存泄漏?
是的,在Internet Explorer中。它从该代码创建了两个不同的函数。有关详细信息,请参阅http://kangax.github.com/nfe/#jscript-bugs
为什么abc.prototype是函数def?
不是。这只是一个对象。也许它在您的控制台中以该名称显示,属于名为“def”的函数。
答案 1 :(得分:5)
这是named function expressio n。可能的用途可能是:
var abc = function def() {
def.test = 'Wait!'; //< sort of a static property
console.log(def.test+" What??");
}
但是beware。
答案 2 :(得分:2)
函数表达式 也可以有名字;函数表达式的名称仅在函数体 1 的范围内。 (由于ECMAScript第5版弃用arguments.callee
,这是编写递归“匿名”函数的唯一简单方法。)
因为 是一个函数表达式,名称可能不会 1 在外部作用域中引入新的绑定。
此外,所有函数都是JavaScript中的对象。在f(..)
中,f
在之前评估,并使用(..)
“调用”;如果f
未评估函数,则抛出错误。这就是回调,它只是函数,可以通过变量命名并作为参数传递。
另外,检查关于原型的假设/断言:
var abc = function def() {}
abc.prototype === abc // -> false
abc.name // -> "def"
1 见Bergi的答案。
2 如何轻松辨别哪个是哪个?
语法规则仅允许function ..
在SourceElement时被解析为函数声明,尽管大多数引擎仍会[错误地]将函数声明解析为Statement。 SourceElement产品仅出现在程序的顶级“块”或函数的顶级“块”中。
在任何情况下,每当需要 Expression的地方出现function ..
时,将解析为功能表达。 all 解析为函数表达式的示例:
// Can only assign values: Statements do not have values!
var f = function () {}
var g = function gName () {} // see Bergi's answer
// Can only pass values: Statements do not have values!
doIt(function () {}) // callback / "anonymous function"
// IIFE: Immediately-Invoked Function Expression
;(function () {})() // standard IIFE
;(function () {} ()) // alternative standard IIFE
;+function () {} () // curious way to write an IIFE
// basically you can use any unary operator to turn it into an expression not only
// + but also - ! ~ and so on which will modify the return value accordingly
关键是,在每个单个上述一个案例中,function ..
出现在语法位置需要一个表达式,因此被解析为一个函数表达。 (上面一行开头的分号避免了ASI的“歧义”,这是以我喜欢的无分号风格书写时所必需的。)
然而。 ;function () {} ()
和;function f () {} ()
都是无效的语法 - 为什么? ; - )
答案 3 :(得分:2)
这是一个命名的函数表达式。
与函数声明相反,函数表达式的标识符不是必需的。
您的函数def
未立即调用 - 整个函数将传递给abc
,需要明确调用abc()
。
§13说明了如何构建命名函数表达式。阅读有关如何构建命名函数表达式的第三个生成规则。
注意可以引用FunctionExpression中的标识符 在FunctionExpression的FunctionBody中允许该函数 递归地称呼自己。但是,与FunctionDeclaration不同, FunctionExpression中的标识符无法引用和执行 不影响包含FunctionExpression的范围。
所有最近的浏览器都能正确处理这个问题,因此您不必担心内存泄漏或其他奇怪的事情(不正确的处理仅在旧的IE&lt; = 8中)。
答案 4 :(得分:1)
您的示例是(命名)函数表达式。
两者之间的区别在于浏览器加载它们的方式。
在任何代码执行之前加载函数声明 只有当解释器到达代码的行时,函数表达式才会加载。
这意味着:
abc();
var abc = function() {
console.log("Wait! What??");
}
无效,但是:
def();
function def() {
console.log("Wait! What??");
}
威尔
现在在您的示例中,您可以访问def
,但只能访问函数本身。
var abc = function def() {
console.log(def);
}
abc();
// Logs:
//function def() {
// console.log(def);
//}