Uncaught TypeError: (intermediate value)(...) is not a function

新手上路,请多包涵

当我在闭包中将 js 逻辑编写为单个 js 文件时,一切正常,如下所示:

(function(win){
   //main logic here
   win.expose1 = ....
   win.expose2 = ....
})(window)

但是当我尝试在同一个 js 文件中的闭包之前插入一个日志记录替代函数时,

 window.Glog = function(msg){
     console.log(msg)
 }
 // this was added before the main closure.

 (function(win){
   //the former closure that contains the main javascript logic;
 })(window)

它抱怨有一个TypeError:

Uncaught TypeError: (intermediate value)(...) is not a function

我做错了什么?

原文由 armnotstrong 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2k
2 个回答

该错误是第三行缺少分号的结果:

 window.Glog = function(msg) {
 console.log(msg);
 }; // <--- Add this semicolon

 (function(win) {
 // ...
 })(window);

ECMAScript 规范 对自动插入分号有特定的规则,但是在这种情况下不会自动插入分号,因为从下一行开始的带括号的表达式可以解释为函数调用的参数列表。

这意味着如果没有该分号,匿名 window.Glog 函数将被调用,并使用一个函数作为 msg 参数,然后是 (window) ,它随后试图调用返回的任何内容。

这就是代码的解释方式:

 window.Glog = function(msg) {
 console.log(msg);
 }(function(win) {
 // ...
 })(window);

原文由 Josh Crozier 发布,翻译遵循 CC BY-SA 3.0 许可协议

简化分号规则

( , [ , ` 或任何算术运算符开头的每一行,如果您希望它被解释为自己的行,则 必须 以分号开头 ~ 否则,它可能偶然与上一行结合。所有其他换行符都有隐式分号。

而已。完毕。

  • 请注意,无论如何,/、+、- 是您唯一想要执行此操作的有效运算符。您永远不会希望一行以“*”开头,因为它是一个二元运算符,在一行的开头永远没有意义。

  • 执行此操作时,您应该将分号放在行的 _开头_。您不应尝试通过 在前 一行添加分号来“解决”问题,否则代码的任何重新排序或移动都可能导致问题再次出现。许多其他答案(包括最佳答案)都提出了这个建议,但这不是一个好习惯。


为什么那些特定字符需要初始分号?

考虑以下:

 func()
;[0].concat(myarr).forEach(func)
;(myarr).forEach(func)
;`hello`.forEach(func)
;/hello/.exec(str)
;+0
;-0

通过遵循给定的规则,您可以防止上述代码被重新解释为

func()[0].concat(myarr).forEach(func)(myarr).forEach(func)`hello`.forEach(func)/hello/.forEach(func)+0-0

补充笔记

提一下会发生什么:括号将索引,括号将被视为函数参数。反引号将转换为 标记模板,正则表达式将转换为除法,显式 +/- 符号整数将转换为加/减运算符。

当然,你可以通过在每个换行符的末尾添加一个分号来避免这种情况,但 不要 相信这样做可以让你像 C 程序员一样编码。由于情况仍然如此,当您 以分号结束一行时,Javascript 可能会违背您的意愿隐式地为您添加一个分号。所以,请记住像这样的陈述

return       // Implicit semicolon, will return undefined.
    (1+2);

i        // Implicit semicolon on this line
   ++;   // But, if you really intended "i++;"
         // and you actually wrote it like this,
         // you need help.

上面的case会恰好return/continue/break/++/–。任何 linter 都会捕获前一种情况的死代码,或后一种情况的 ++/– 语法错误。

最后,如果您希望文件串联起作用,请确保每个文件都以分号结尾。如果您使用的是捆绑程序(推荐),它应该会自动执行此操作。

原文由 Nicholas Pipitone 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题