var fn = function{…}和var fn = function foo{…}是否曾经有所不同?

问题描述

| 当您将函数分配给变量时,如果您使用命名函数而不是匿名函数,那么它根本没有任何区别。以下将生成错误“ \“ foo()未定义\”。
var fn = function foo(){...};
foo();
谁能弄清楚这里发生了什么?     

解决方法

        您正在创建一个命名函数表达式。 除IE外,该名称仅在函数内部可见。     ,        在您的示例中,变量
fn
在当前作用域中是可访问的,而
foo
仅在函数作用域中是可访问的。例如:
var bar = function foo() {    
    document.write(\"Internally,Foo is \" + typeof foo + \"<br/>\");
    document.write(\"Internally,Bar is \" + typeof bar + \"<br/>\");
};

document.write(\"Foo is \" + typeof foo + \"<br/>\");
document.write(\"Bar is \" + typeof bar + \"<br/>\");

bar();
将产生:
Foo is undefined
Bar is function
Internally,Foo is function
Internally,Bar is function
http://jsfiddle.net/robert/TEnjb/     ,        因为未定义(
foo
);-) 在这种情况下,“ 6”是一个函数表达式(\“ FunctionExpression \”),而不是一个函数语句(\“ FunctionDeclaration \”)-语法中有两个不同的产生式。只有功能声明形式[魔术地]将功能名称分配(并提升分配)给适当的变量。即使使用function-expression创建的函数也可以具有名称,它恰好是可选的,但是没有其他形式的隐式赋值。 [编辑:显然,这比我想象的要古怪。在任何情况下,以上情况均适用于适当兼容的浏览器。例如,Gecko具有\“ function语句扩展名,这是不符合的,而IE / JScript表现出不同的行为,这也是不符合的。根据语法规范,这两种都是错误的实现。] 考虑以下内容,这应该可以说明为什么[[more]兼容实现)会理智地引发异常:
// `function` is just an expression here -- there is no good reason for it to
// cause an implicit side-effect. And,according to the specification,it will not.
(function foo () {}).name // \"foo\",at least in FF
foo // undefined
附带说明:任何不是顶级语句或直接在功能块内部的语句的函数产生都是函数表达式。在不同的浏览器中,以下行为是古怪的:
foo() // works in IE (this should never work)
if (true) {
   // this is an INVALID GRAMMAR production,although it is accepted in browsers,// with different operational semantics
   function foo () {
   }
}
foo() // works in FF and IE (this should never work)
快乐的编码。 简短介绍ECMAScript规范,以讨论语法。尽管我找到了Ed,但在这里同样可以找到“规则”。 5以最容易混淆的方式编写。 (它错过了所有树木的森林……) FunctionExpression的语法:
// There is a silly long expression tree to get here.
// Look it up if you want :)
FunctionExpression : function Identifier [optional] ( FormalParameterListopt ) { FunctionBody }
FunctionDeclaration(在上面我称为功能声明)和相关联的“链”的语法:
 FunctionBody : SourceElements [optional] 
 Program : SourceElements [optional]  
 SourceElements : SourceElement 
                  SourceElements SourceElement
 SourceElement : Statement
                 FunctionDeclaration 
 FunctionDeclaration : function Identifier ( FormalParameterListopt ) { FunctionBody } 
请注意,没有针对“ INVALID GRAMMAR \”的语法规则。到达FunctionDeclaration的唯一方法是通过SourceElement,该SourceElement仅在FunctionBody或Program内部有效(不包括诸如“ 11”之类的其他块)。如下所示,\“正则表达式\”作为FunctionExpression受到限制:        ExpressionStatement不能以大括号开头,因为这可能会使它与Block产生歧义。另外,ExpressionStatement不能以function关键字开头,因为这可能会使它与FunctionDeclaration产生歧义。    ...以及规范中的适当注释:        已知有几种广泛使用的ECMAScript实现支持使用FunctionDeclaration作为语句。但是,在应用于此类FunctionDeclaration的语义中,实现之间存在重大而又不可调和的变化。由于存在这些无法协调的差异,因此将FunctionDeclaration作为Statement的使用会导致代码无法在实现之间可靠地移植。        ,        从技术上讲,
fn
是指向\“ foo \”的函数指针,但是您实际上并没有在Javascript中看到它。您实际上应该只写:
function foo() {
  /* ... */
}

foo();
正如其他人指出的那样,您的分配仅使makes2ѭ函数\“ live \”处于
fn
的范围内,因此,当
fn
超出范围时,原则上可以清除函数对象。如果确实有令人信服的理由,请使用函数指针,否则可以只将函数保持全局。     ,        在某些版本的IE上,这是可行的,但这仅是因为它们不符合要求。
var fn  // declares a variable named fn
    = function  // initializes fn
      foo  // declares a name foo that is only visible within the function body.
      (){
        ...  // foo is visible here.
      };
foo();  // foo is not defined here (except on IE 6 and earlier)
fn();  // works just fine.
    ,还请注意,尽管经常说:
function foo() {
};
只是用于以下目的的语法糖:
var foo = function() {
};
实际上并非如此。 在前一种情况下,解析脚本时,无论文件中的定义顺序如何,命名函数都立即可用。 在后者中,将立即解析匿名函数主体,但是直到执行该行代码后,才将其分配给局部作用域的变量。这意味着在此之前执行的任何代码都不能调用
foo()
。     ,        根据作用域和定义函数的方式,它可以是函数声明,函数表达式或函数语句。这三种函数类型的处理和加载方式有所不同。其中,仅函数声明需要名称。因此,可以在没有名称的情况下定义另外两个类型。这三种类型在它们分配给具有函数名称的变量的方式上也不同。 函数声明:在顶级范围中定义,不在其他表达式/语句中使用(例如,未分配给变量)
 function foo(){}
功能对象在全局范围内分配给变量“ 2”。 函数表达式:在另一个表达式/语句中定义。
 var bar = function foo(){}
函数对象被分配给变量
foo
,但在内部作用域(即函数内部的作用域)中 函数语句:它们可以在允许使用纯语句的任何地方。
if (true) {
  function foo(){ }
}
函数对象在外部作用域中分配给变量
foo
(即,作用域包含函数定义)。 有关更多信息,请参见以下地址:http://kangax.github.com/nfe/