【问题标题】:Javascript: Inconsistency when assigning a named function to a variable (named function expression)Javascript:将命名函数分配给变量时的不一致(命名函数表达式)
【发布时间】:2013-01-21 19:55:54
【问题描述】:

谁能解释一下 Internet Explorer 和 Firefox 在以下方面的行为差异:

var myNamespace = (function () {
  var exposed = {};

  exposed.myFunction = function myFunction () {
    return "Works!";
  }

  console.log(myFunction()); 
  // IE: "Works!"
  // Firefox: ReferenceError: myFunction is not defined

  console.log(exposed.myFunction());
  // IE: "Works!"
  // FF: "Works!"

  return exposed;
})();

console.log(myNamespace.myFunction()); 
// IE: "Works!"
// FF: "Works!"

在 Internet Explorer 中,此方法允许我使用 myFunction()exposed.myFunction() 从命名空间函数内部调用我的函数。

在我的命名空间函数之外,我可以使用myNamespace.myFunction()

在 Firefox 中,结果是相同的,只是裸命名函数调用不起作用。

应该有效吗?如果不应该,那为什么不呢?

如果应该那么这是一个已知的错误吗?

【问题讨论】:

标签: javascript internet-explorer firefox cross-browser


【解决方案1】:

这个:

exposed.myFunction = function myFunction () {
    return "Works!";
}

没用(- 纠正我自己:这不是不正确的 - )并且显然有问题(请参阅 Felix 的帖子)。如果您希望声明 exposed 的函数部分,则无需命名:

exposed.myFunction = function() {
    return "Works!";
}

但是,如果你想声明一个本地函数然后也影响到你的数组exposed,你可以这样做:

function myFunction () {
    return "Works!";
}

exposed.myFunction = myFunction;

在这种情况下,它将成功验证 (exposed.myFunction === myFunction) === true;

另外,请注意,您对console.log(myNamespace.myFunction()); 的调用与您对console.log(exposed.myFunction()); 的调用相同,因为myNamespace 实际上是对象exposed

【讨论】:

  • 这是不正确的。这是一个命名函数表达式和完全有效的 JavaScript。
  • 那么firefox应该允许console.log(myFunction());的执行,否则会出现不一致。
  • 不,IE 应该正确实现 JavaScript。
  • 我的意思是,如果你说第一个表达式是正确的,那么这意味着应该在当前上下文中考虑裸 myFunction 的声明,因此按原样调用是有效的。
  • 但这不是函数表达式的定义方式。看我的回答。
【解决方案2】:

为防止虚假信息:

IE 的 命名函数表达式 存在问题,这就是您所拥有的。函数的名称应该只在函数内部可用。来自specification

FunctionExpression 中的 Identifier 可以从 FunctionExpressionFunctionBody 内部引用以允许该函数递归调用自身。但是,与 FunctionDeclaration 不同,FunctionExpression 中的 Identifier 不能被引用,并且不会影响包含 FunctionExpression。

其中FunctionExpression定义为:

函数表达式 :
function 标识符opt( FormalParameterListopt ) { FunctionBody }

但在 IE 中,它并没有使名称仅在函数内部可用,而是创建了两个不同函数对象,一个分配给变量,另一个分配给您为函数指定的名称。以下将在 IE 中产生 false(并在其他浏览器中抛出错误):

exposed.myFunction === myFunction;

这是一个已知的错误,如果您必须为(旧版本的)IE 编写代码,您最好避免使用命名函数表达式。


相关问题:

【讨论】:

  • 太棒了!这完美地解释了为什么上面的代码在 IE 中而不是在 Firefox 中“有效”。当然,Firefox 中的行为不是我所期望的,而是符合规范的,这很重要。
  • console.log(myFunction());,适用于 IE,是对根据您的规范应该存在的本地函数的调用。 (在这种情况下,FunctionBody 是最接近 exposed 的信封,正是进行裸调用的地方)
  • @Sebas:不,我们谈论的是 FunctionExpression 的 FunctionBody,而不是它定义的 FunctionBody。也许你还没有看到我的更新。根据规范,它应该存在。
  • 我明白你的意思。也许我解释错了,但对我来说这里有一个问题,因为我们正在谈论声明函数及其相关范围(我 100% 同意你的帖子),而实际上存在覆盖函数的影响。见我的帖子:函数的声明肯定在exposed 的主体之外,即使之后,它作为一个属性受到它的影响。但也许我误解了引擎。
  • @Sebas:说实话,我无法关注您的最后评论。手头的问题是 IE 在定义函数的范围内创建了一个带有函数表达式名称的符号,这是错误的。其他一切都无关紧要。
【解决方案3】:

另外,通过定义

exposed.myFunction = function() {}

您将exposed属性 设置为myFunction

并且它在myNamespace 范围内不可用。

通过定义

exposed.myFunction = function myFunction() {}

函数在myNamespace的范围内创建,然后作为exposed的属性引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-16
    • 1970-01-01
    • 2016-12-02
    • 2012-01-22
    • 2012-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多