关于oop:知道javascript函数表达式和函数声明,但这是什么?命名函数表达式?

Know JavaScript Function Expression vs Function Declaration, but what is this? Named Function Expression?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
What is the difference between a function expression vs declaration in Javascript?

我知道函数声明和表达式之间的区别,但是遇到了涉及函数名的代码,我想了解运行它时会发生什么:

1
2
3
var abc = function def() {
    console.log("Wait! What??");
}

我知道这不是JavaScript的一种方法,但我只想知道以下几点:

  • abc发生了什么?为什么工作?可以调用abc,但不能调用def,为什么?
  • 它是函数声明还是表达式?
  • defundefined为什么?如果应该的话,有吗内存泄漏?
  • 为什么abc.prototype是函数def
  • 谢谢


    What happens to abc?

    它包含一个函数对象。如果你什么都不做,它将被垃圾收集。

    Why it works?

    为什么不?"工作"是什么?

    abc can be called but not def, why?

    这只在外面是正确的,而不是在IE中。见下文。

    Is it a function declaration or an expression?

    它是一个函数表达式。您可以很容易地看到,因为它是赋值表达式的一部分;声明总是需要位于顶层(函数或全局代码)。

    def is undefined - why?

    只有从外面。函数表达式不创建变量。"def"是函数的名称,函数内部也是对函数的引用。例如,这允许递归而不使用任何外部变量。

    1
    2
    3
    4
    5
    6
    var abc = function def() {
        def === abc; // true
        def.name; //"def"
    }
    abc();
    def; // undefined

    If it is supposed to be, are there memory leaks?

    是,在Internet Explorer中。它从该代码创建了两个不同的函数。有关详细信息,请参阅http://kangax.github.com/nfe/jscript bugs

    Why is abc.prototype is function def?

    不是这样。它只是一个物体。也许它在控制台中以这个名称显示,因为它属于一个名为"def"的函数。


    它是一个命名函数表达式。可能的用途是:

    1
    2
    3
    4
    var abc = function def() {
        def.test = 'Wait!'; //< sort of a static property
        console.log(def.test+" What??");
    }

    但要当心。


    它是一个命名函数表达式。

    与函数声明相反,函数表达式的标识符不是必需的。

    您的函数def没有立即调用—整个函数被传递给abc,需要明确地调用abc()

    ES5规范的第13节说明了如何构建命名函数表达式。阅读关于如何构建命名函数表达式的第三条生成规则。

    NOTE The Identifier in a FunctionExpression can be referenced from
    inside the FunctionExpression's FunctionBody to allow the function to
    call itself recursively. However, unlike in a FunctionDeclaration, the
    Identifier in a FunctionExpression cannot be referenced from and does
    not affect the scope enclosing the FunctionExpression.

    所有最近的浏览器都能正确地处理这个问题,因此您不必担心内存泄漏或其他奇怪的事情(不正确的处理只在旧的IE<=8中)。


    它是一个函数表达式2

    函数表达式也可以有名称;函数表达式的名称只在函数体1的作用域中。(由于ecmascript第5版反对arguments.callee,这是编写递归"匿名"函数的唯一简单方法。)

    因为它是一个函数表达式,所以名称不能1在外部作用域中引入一个新的绑定。

    此外,所有函数都是JavaScript中的对象。在f(..)中,f在用(..)进行"调用"之前进行评估;如果f没有对函数进行评估,则抛出一个错误。这就是为什么回调(只是函数)可以通过变量命名并作为参数传递。

    另外,检查关于原型的假设/断言:

    1
    2
    3
    var abc = function def() {}
    abc.prototype === abc // -> false
    abc.name              // ->"def"

    1看伯吉的回答。

    2.如何轻松分辨哪个是哪个?

    语法规则只允许在function ..是sourceElement时将其作为函数声明进行解析,尽管大多数引擎仍然[错误地]将函数声明作为语句进行解析。源元素生成只发生在程序的顶级"块"或函数的顶级"块"上。

    在任何情况下,只要有一个function ..出现在需要表达式的地方,它就会被解析为函数表达式。所有被解析为函数表达式的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 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 () {} ()都是无效语法——为什么?;-)


    您的示例是一个(命名的)函数表达式。

    两者之间的区别在于浏览器如何加载它们。

    在执行任何代码之前加载函数声明。只有当解释器到达该行代码时,才会加载函数表达式。

    这意味着:

    1
    2
    3
    4
    abc();
    var abc = function() {
        console.log("Wait! What??");
    }

    不起作用,但:

    1
    2
    3
    4
    def();
    function def() {
        console.log("Wait! What??");
    }

    威尔。

    现在,在您的示例中,您可以访问def,但只能在函数本身内部访问。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var abc = function def() {
        console.log(def);
    }
    abc();

    // Logs:
    //function def() {
    //    console.log(def);
    //}