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

知道JavaScript函数表达式和函数声明,但这是什么?命名函数表达式?,javascript,oop,Javascript,Oop,可能重复: 我知道函数声明和表达式之间的差异,但是我遇到了涉及函数名的代码,我想了解在运行它时会发生什么: var abc = function def() { console.log("Wait! What??"); } 我知道这不是JavaScript的一种方式,但我只想知道几件事: abc的情况如何?为什么有效abc可以调用,但不能调用def,为什么 它是函数声明还是表达式 def是未定义的-为什么?如果它应该是,有吗 内存泄漏 为什么abc.prototype是函数def

可能重复:

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

var abc = function def() {
    console.log("Wait! What??");
}
我知道这不是JavaScript的一种方式,但我只想知道几件事:

  • abc的情况如何?为什么有效
    abc
    可以调用,但不能调用
    def
    ,为什么
  • 它是函数声明还是表达式
  • def
    未定义的
    -为什么?如果它应该是,有吗 内存泄漏
  • 为什么
    abc.prototype
    是函数
    def
  • 谢谢

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

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

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

    这意味着:

    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);
    //}
    
    这是一个2

    函数表达式也可以有名称;函数表达式的名称仅在函数body1的作用域中。(由于ECMAScript第5版不推荐
    参数。被调用方
    ,因此这是编写递归“匿名”函数的唯一简单方法。)

    因为它是一个函数表达式,所以名称可能不会在外部范围中引入新的绑定

    此外,所有函数都是JavaScript中的对象。在
    f(…)
    中,在使用
    (…)
    进行“调用”之前对
    f
    进行评估;如果
    f
    未对函数求值,则抛出错误。这就是回调函数可以用变量命名并作为参数传递的原因

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

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

    我看Bergi的答案

    2.如何轻松辨别哪个是哪个

    语法规则仅允许在函数声明为时将
    function..
    解析为函数声明,尽管大多数引擎仍会[错误地]将函数声明解析为函数声明。SourceElement产品仅发生在程序的顶级“块”或函数的顶级“块”上

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

    // 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的“歧义”,这是我喜欢的不使用分号的写作风格所必需的。)

    不过<代码>;函数(){}()和
    ;函数f(){}()
    都是无效语法-为什么?;-)

    这是一个n。这可能的用途是:

    var abc = function def() {
        def.test = 'Wait!'; //< sort of a static property
        console.log(def.test+" What??");
    }
    
    var abc=函数def(){
    def.test='Wait!';//<类似于静态属性
    控制台日志(定义测试+“什么?”);
    }
    

    但是。

    它是一个命名函数表达式

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

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

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

    注意:FunctionExpression中的标识符可以从 在FunctionExpression的FunctionBody中允许函数 递归地调用自己。但是,与函数声明不同 FunctionExpression中的标识符不能从中引用,并且不能引用 不影响包含FunctionExpression的范围

    所有最近的浏览器都能正确处理这个问题,所以你不必担心内存泄漏或其他奇怪的事情(错误的处理只在旧的IE中出现) abc怎么了

    它包含一个函数对象。如果您不使用它,它将被垃圾收集

    为什么有效

    为什么不?什么“有效”

    abc可以调用,但不能调用def,为什么

    这只适用于外部,不适用于IE。见下文

    它是函数声明还是表达式

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

    def未定义-为什么

    仅从外部。函数表达式不创建变量。“def”是函数的名称,在函数内部也是函数的引用。这允许递归,例如不使用任何外部变量

    var abc = function def() {
        def === abc; // true
        def.name; // "def"
    }
    abc();
    def; // undefined
    
    如果应该是,是否存在内存泄漏

    是的,在Internet Explorer中。它使用该代码创建两个不同的函数。有关详细信息,请参阅

    为什么abc.prototype是函数def


    它不是。它只是一个对象。它可能在控制台中以该名称显示,因为它属于名为“def”的函数。

    它是一个命名函数表达式。
    def
    可以在函数内部使用
    def
    来引用它自己。不过要注意浏览器的怪癖(即)您可能还没有读过这些问题及其答案:并且应该为您提供所有答案。我不认为这个问题是一个骗局,因为它专门询问变量名和函数名不同的情况(即使它是由其中一个问题的答案之一回答的)1.这不是重复的2.已经添加的问题