知道JavaScript函数表达式与函数声明,但这是什么?命名函数表达式?

时间:2013-01-17 08:12:12

标签: javascript oop

  

可能重复:
  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的一种方式,只是想知道一些事情:

  1. abc会怎样?为什么会这样?可以调用abc但不是def,为什么?
  2. 是函数声明还是表达式?
  3. defundefined - 为什么?如果它应该是,那里 内存泄漏?
  4. 为什么abc.prototype是函数def
  5. 由于

5 个答案:

答案 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)

这是Function Expression 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()

ES5规范的

§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);
//}