【问题标题】:Understanding callbacks and related lexical scoping理解回调和相关的词法作用域
【发布时间】:2016-03-12 06:27:14
【问题描述】:

我试图通过setTimeout 函数了解回调。 我有两组代码:

for (var i = 1; i <= 10; i++) {
        (function(callback,i){
          setTimeout(function(){
            callback(i)
          }, 0);
         })(function(val){console.log(val)},i);

它可以很好地打印 1,2,3,.... 10

但是当我试图将setTimeout的回调函数抽象为:

for (var i = 1; i <= 10; i++) {
        (function(callback,i){
          setTimeout(func, 0);
         })(function(val){console.log(val)},i);
        }
function func(){
    callback(i)
  }

它给了我错误说明

Uncaught ReferenceError: callback is not defined

我知道该 func 函数声明的词法范围存在一些问题。但无法理解原因。 请帮助我理解这一点。

【问题讨论】:

    标签: javascript callback lexical-scope


    【解决方案1】:

    它抛出引用错误,因为函数func 它的作用域没有callback 的声明。您可以通过将回调作为参数传递给func 来修复它。

    for (var i = 1; i <= 10; i++) {
      (function(callback, i) {
        setTimeout(func, 0, callback.bind(null, i)); //Pass the callback here as a parameter to func. 
                                       //(setTimeout can pass its >2 parameter as 
                                       //its callback parameter)
      })(function(val) {
        console.log(val)
      }, i);
    }
    
    function func(callback) { //receive the callback here and use it.
      callback();
    }
    

    【讨论】:

    • IE9 及更早版本不支持 u 用于将参数传递给 func 的语法
    • @RIYAJKHAN IE 9 死了! Microsoft 停止为其提供支持。
    • 是的,我知道。但是时间很长,所以没有一个应用程序可以在上面运行
    【解决方案2】:

    callback 未在 func 中定义。您可以将func 作为参数传递给IIFE,使用Function.prototype.bind()i 传递给callbackfunc

    for (var i = 1; i <= 10; i++) {
      (function(callback, i) {
        setTimeout(callback.bind(null, i), 0);
      })(func, i);
    }
    
    function func(val) {
      console.log(val)
    }

    【讨论】:

    • 您的答案与 OP 的解决方案非常相似。他使用了匿名函数,而您使用了绑定。两者都是一样的。但是 OP 在问为什么他的第二个 sn-p 不起作用。代码中func 的用途是什么?
    • “但是 OP 在问为什么他的第二个 sn-p 不起作用。你的代码中 func 的目的是什么?” func 作为参数传递给 IIFE ,在 IIFE 中被称为callback.bind() 不调用 func : callback,但将 func : callback 的引用传递给 setTimeout 并以 i 作为参数。您是否尝试过发布的解决方案? ,似乎将11 记录到console 十次?
    • 我没有注意到我的代码打印了 11 十次。谢谢指点。
    【解决方案3】:

    func 中,您没有引用您在 IIFE 中声明的callback。因此,它开始在当前范围内查找,即您的func 范围。然后它尝试在全局范围内查找,它也没有在那里定义。最后它抛出一个错误

    您需要将引用传递给引用该函数的回调参数以消除此错误。

    for (var i = 1; i <= 10; i++) {
            (function(callback,i){
              setTimeout(func.bind(null,callback,i), 0);
             })(function(val){console.log(val)},i);
            }
    function func(callback,i){
        callback(i)
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-26
      • 2017-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-03
      相关资源
      最近更新 更多