“ {...}不是函数”,尽管从未调用为函数

时间:2018-12-21 09:30:58

标签: javascript typeerror

如果我在匿名函数调用之前立即创建JSON对象,则在Firefox中会得到TypeError: ({x:0, y:0}) is not a function,在Chrome中会得到Uncaught TypeError: {(intermediate value)(intermediate value)} is not a function

但是,我从未将a称为函数。另外,当我在对象定义后加上分号时,不会发生此错误。

根据http://inimino.org/~inimino/blog/javascript_semicolons,我不明白为什么从理论上讲我为什么需要在其中使用分号。但是,由于某些原因,仍然需要它。为什么?

let a = { x: 0, y: 0 }

(() => {
    console.log('test')
})()

4 个答案:

答案 0 :(得分:5)

就像其他人所说的那样,这两个语句被视为一个单一的,无意义的语句。我的担心是,没有人正确地回答了为什么在这里而不是在其他情况下发生的情况。

您在此处引用了NPM样式指南:https://docs.npmjs.com/misc/coding-style.html 它说

  

在行首(或[在行的开头。]的前面。这可以防止将表达式分别解释为函数调用或属性访问。

所以您的问题是因为第二条语句以([开头,这使解析器感到困惑。在这些情况下,需要使用分号。 为什么解析器会被([混淆?因为例如{ x: 0, y: 0}["x"]是有效的代码。与{ x: 0, y: 0}()相同,它是完全有效的,它将崩溃。但是解析器无法知道是否有意义,因此必须在各处应用相同的规则。

请注意,npm样式指南随后说在这种情况下,将分号与(放在一行上。所以你会写:

let a = { x: 0, y: 0 }

;(() => { // semi-colon at start of this line
    console.log('test')
})()

这样做的原因是,如果将其放在第一个语句之后,然后再编辑代码,则会重新引入该问题。例如,最终结果如下:

let a = { x: 0, y: 0 };

let b = { x: 1, y: 1 }

(() => { // this will fail
    console.log('test')
})()

答案 1 :(得分:4)

您尚未终止对x的分配,因此引擎看到您正在调用函数:

// Wrong:
let {x: 0, y:}()();

您应使用分号终止:

let a = { x: 0, y: 0 }; // terminate this line with a semi-colon ;

(() => {
    console.log('test')
})()

之所以这样,是因为如果没有分号,则这两个语句将被读为一个,  反过来没有道理。

答案 2 :(得分:0)

相反会引发TypeError,JavaScript会尝试将其解释为

let a = { x: 0, y: 0 }(
    () => {console.log('test')}
)()

详细信息参考: https://flaviocopes.com/javascript-automatic-semicolon-insertion/

答案 3 :(得分:0)

始终使用分号,因为Javascript编译器从上到下逐行编译代码,因此在您的情况下,它解释为

let a = { x: 0, y: 0 } (() => { console.log('test') })()

,编译器无法确定该行在哪里终止,并且func同时执行,这对编译器没有意义。 这就是为什么您遇到提到的TypeError的原因。

要解决此问题,请在定义对象后使用分号

let a = { x: 0, y: 0 } ;
(() =>  console.log('test') )();

由于函数不返回任何值(使用es6属性),因此您也可以删除花括号来重构代码(只是一点建议)。