调用回调时未捕获的 TypeError

Uncaught TypeError when invoking callbacks

我遇到了一个错误,我已自行解决。有人可以向我解释为什么我的代码不起作用以及导致它的机制。

代码如下:

var listTables = function (tables) {
  console.log(tables);
}

var ajaxReq = function (success_cb, url) {
  // success_cb can be invoked here without errors
  var http = new XMLHttpRequest();
  http.onreadystatechange = function (success_cb) {
    if (this.readyState == 4 && this.status == 200) {
      success_cb(this); // Uncaught TypeError: success_cb is not a function
    }
  }
  http.open("GET", url, true);
  http.send();
}
ajaxReq(listTables, "http://www.someurl.com");

当我从 onreadystatechange 函数定义中删除 success_cb 回调时,代码工作正常。这是与范围相关的问题吗?

错误是你在inner函数中重复了success_cb作为参数:

var ajaxReq = function (success_cb, url) { // First time success_cb parameter is used: correct.
  var http = new XMLHttpRequest();
  http.onreadystatechange = function (success_cb) { // Second time: wrong!
    // ...
  }
  // ...
}

这做了两件意想不到的事情:

  • 它掩盖了你原来的(第一个)success_cb,所以它不能再访问了
  • 而是将 readystatechange 事件的 事件参数 分配给 success_cb,这是一个对象

Overshadowing”的意思是,提供了一个同名的变量(或参数),其范围比前一个更接近

所以只需删除第二个用法:

var listTables = function (tables) {
  console.log(tables);
}

var ajaxReq = function (success_cb, url) {
  // success_cb can be invoked here without errors
  var http = new XMLHttpRequest();
  http.onreadystatechange = function () {
    if (this.readyState == 4 && this.status == 200) {
      success_cb(this);
    }
  }
  http.open("GET", url, true);
  http.send();
}
ajaxReq(listTables, "http://www.someurl.com");