开发者问题收集

未捕获的类型错误:(中间值)(…)不是函数

2017-02-04
425540

当我将 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

我做错了什么?

3个回答

此错误是由于第三行缺少分号造成的:

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
2017-02-04

简化分号规则

如果希望将以 ([ 、` 或任何算术运算符开头的每一行解释为自己的行,则必须以分号开头 ~ 否则,它可能会意外地与前一行合并。所有其他换行符都有隐式分号。

就是这样。完成。

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

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


为什么这些特定字符需要以分号开头?

考虑以下内容:

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.

的语句,上述情况将发生在 return/continue/break/++/-- 中。任何 linter 都会捕获前一种情况(死代码)或后一种情况(++/-- 语法错误)。

最后,如果您希望文件连接正常工作,请确保每个文件都以分号结尾。如果您使用的是打包程序(推荐),它应该会自动执行此操作。

Nicholas Pipitone
2018-09-28

错误案例:

var userListQuery = {
    userId: {
        $in: result
    },
    "isCameraAdded": true
}

( cameraInfo.findtext != "" ) ? searchQuery : userListQuery;

输出:

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

修复: 您缺少一个分号 (;) 来分隔表达式

userListQuery = {
    userId: {
        $in: result
    },
    "isCameraAdded": true
}; // Without a semi colon, the error is produced

( cameraInfo.findtext != "" ) ? searchQuery : userListQuery;
Shashwat Gupta
2017-12-07