问题

碰到了一个很诡异的问题,函数明明定义了,却报错说函数没定义,代码如下:

jsvar x = 0;
var foo = function(callback){
  return window.setTimeout(callback, 17);
}  
(function sayX(){
  x += 1;
  console.log(x);
  foo(sayX);
}())

报错信息: Uncaught TypeError: foo is not a function
测试环境: chrome 44.0.2403.130 m

解决

后来经过提问,和查找资料, 大概明白了其中的缘由,故写此文。

这个问题涉及到一个"自动分号插入",具体到这个问题,就是:
1. 函数声明自动插入引号;
2. 函数表达式不会自动插入分号;

function foo() {
}  // 函数声明会自动添加分号,不需要添加分号

var foo = function() {
}; // 函数表达式不会自动添加分数,最好添加分号

具体到这个问题,由于foo 函数表达式后面没有分号,于是代码等价于:

jsvar x = 0;
var foo = function(callback){
  return window.setTimeout(callback, 17);
}(function sayX(){
  x += 1;
  console.log(x);
  foo(sayX);
}())

插播一条知识点:
函数表达式后面跟括号就会对触发函数执行,比如

var foo = function(x){
  return x;
}(10)  

最终 foo 的值是 10 ,而不是函数

回到这个问题, 自调用函数会首先取值, 然后传入函数求值,返回给foo。
但自调用函数求值过程中遇到 foo(sayX)时,foo还没有值,所以会报Uncaught TypeError: foo is not a function的错误。

此时,真相大白。

感悟

不要省略分号.

感谢

  1. http://segmentfault.com/q/1010000003074238
  2. http://justjavac.iteye.com/blog/1852405

杨军军
1.3k 声望26 粉丝