为什么“TypeError: f 不是一个函数”

Why "TypeError: f is not a function"?

本文关键字:一个 函数 TypeError 为什么      更新时间:2023-09-26

下面是示例:

var f = function(x) {
   alert(x)
}
(function() {
   f(1)
}())

为什么

类型错误:f 不是函数"?

在您的示例中,f 不是一个函数。如果更改示例,则为:

var f = function(x) {
   alert(x)
};
(function() {
   f(1)
}());

您已经与自动分号插入(或缺乏分号插入(相冲突。

由于 ASI 规则,如果一行不以分号结尾,则解析器可以组合行。在您的情况下,var f = function语句后缺少分号会导致解析器在初始化f之前声明并立即调用函数,并尝试将结果分配给f

var f = function(x) {
   alert(x)
}(function() {
   f(1)
}())

通过简单地插入分号,您可以强制解析器中断这两个语句,并且代码的行为符合您的预期。

解析器更喜欢将它们组合在一起,因为它看到一个函数和似乎是参数的东西(多亏了前导括号,空格被忽略了(。它调用刚刚声明的函数,然后调用f,但f尚未初始化,因此不是函数。

我在一个旧的 Web 应用程序中遇到了一个特别有趣的案例(在 webpack 和 browserify 存在以合并文件之前(:我们只是按顺序将我们的 JS 文件放在一起,大多数都在 IIFE 模块中。一个脚本在其模块后没有以分号结尾,因此下一个模块在初始化第一个模块时作为参数传递。找到它很痛苦,因为它发生在应用程序的早期,并且是一个丢失的半。

在这种情况下,我们能够通过在连接的文件之间添加注释来解决问题,而无需更改任何外部代码,但好的做法是用分号和换行符结束代码。它避免了像这样的各种罕见的空格错误。

在这种情况下,自动分号插入会让您失望,代码被解释为 IIFE:

var f = function(x) {
   alert(x)
}(function() {
   f(1)
}())

所以这就是为什么f确实没有定义。

所以经验法则:永远不要以([开头。然后,您可以安全地省略分号。