javascript中的回调函数错误

javascript中的回调函数错误,javascript,function,Javascript,Function,我正在学习回调函数。我不明白为什么这两个代码块之间有区别。有人能解释一下吗 function a(callback) { var something = 10; callback(); } a(function() { console.log(something); }); 这是: function a() { var something = 10; (function() { console.log(something); }())

我正在学习回调函数。我不明白为什么这两个代码块之间有区别。有人能解释一下吗

function a(callback) { 
  var something = 10; 

  callback(); 
} 

a(function() { 
  console.log(something); 
}); 
这是:

function a() { 
  var something = 10; 

  (function() { 
    console.log(something); 
  }());
} 

a();
function getUserInput() {

    clientData.setUserName('viet','nguyen')
}
getUserInput();
console.log(clientData.fullName);
// it will return the object clientData and the fullname set to viet nguyen
我还对这两个代码块感到困惑:

var clientData = {
  id: 094545,
  fullName: "Not Set",
  setUserName: function (firstName, lastName) {

    var self = this;
    self.fullName = firstName + " " + lastName;
    console.log(self);
  } }



function getUserInput(firstName, lastName, callback) {

    callback (firstName, lastName);
}

getUserInput('viet','nguyen',clientData.setUserName );
console.log(clientData.fullName);
// It will return the window object and not set
这是:

function a() { 
  var something = 10; 

  (function() { 
    console.log(something); 
  }());
} 

a();
function getUserInput() {

    clientData.setUserName('viet','nguyen')
}
getUserInput();
console.log(clientData.fullName);
// it will return the object clientData and the fullname set to viet nguyen

下面是对第一个代码块对的解释:

  • 当您将函数作为参数从调用者传递给接收函数(被调用者)时,接收方函数可以调用该“回调函数”,不管它是如何定义的

  • 当您在被调用函数中定义一个函数时,这是它可以作为“静态子程序”运行的唯一方法,而不是上面的方法,在这里它可以是what-ever,也可以从任何调用方的参数定义它


  • 通常,一个应用程序需要按顺序执行许多函数,大多数情况下都是这样,比如说你有一个寄存器函数,但当它成功时,你希望引导用户进入下一步。因此,这里我们可以调用一个名为register()的函数,当该函数完成时,它将自动调用我们希望它在成功时执行的函数,或者现在使用多个回调也变得很常见

    现在,在这些情况下,许多人用它来表示成功或失败。使用这些函数时,可以传递两个函数,一个显示成功消息,另一个显示错误。下面的例子

    function register(onsuccess, onfailure) {
        try {
            ... Some logic here ...
            onsuccess();
        }
        catch(err) {
            onfailure();
        }
    }
    
    使用另一种不使用回调的方法,我们必须这样做

    function register() {
        try {
            ... Some logic here ...
            return true;
        }
        catch(err) {
            return false;
        }
    }
    
    if (register()) {
        ... onsuccess logic goes here ...
    } else {
        ... onfailure logic goes here ...
    }
    
    正如您所见,回调方法更易于阅读,也更易于调试和维护

    希望这已经回答了您的问题并澄清了您可能存在的顾虑:)

    编辑:我还想提到,当使用回调函数时,程序员总是更容易创建条件来执行回调

    //它将返回窗口对象,但未设置

    这是因为当函数引用作为参数传递时,执行上下文会发生变化

    function a() { 
      var something = 10; 
    
      (function() { // This is a closure
        console.log(something); // The same `something` defined above
      }());
    } 
    
    a();
    
    这条线

    getUserInput('viet','nguyen',clientData.setUserName );
    
    在全局上下文(
    window
    )中执行,而不是在
    clientData
    的上下文中执行,因此传递的任何参数都是在
    调用方的上下文中传递的

    按照

    让callerContext作为正在运行的执行上下文


    在本例中,callerContext是
    窗口

    这是两个独立的问题

    第一对代码段 问题在于变量的范围。在这个函数中,您在函数
    a
    中声明一个
    something
    。传递到
    a
    的回调声明在
    a
    的范围之外,因此对
    something
    一无所知,因为
    something
    是局部作用域而不是全局作用域

    function a(callback) { 
      var something = 10; // This is a local variable
    
      callback();
    } 
    
    a(function() { 
      console.log(something); // What is `something`??? 
    });
    
    要修复它,您可以像这样将
    某物
    传递到回调中:

    function a(callback) { 
      var something = 10; // This is still a local variable
    
      callback(something);
    } 
    
    a(function(whatever) { 
      // `whatever` is a new local variable that references `something`.
      console.log(whatever);
    });
    
    对于您编写的此函数的另一个版本,
    函数中定义了某个
    ,因为它是在
    a
    函数中定义的,使其成为一个。因此,它是一个closure拥有闭包是很方便的,但是如果您正在编写一个依赖于回调的函数,那么它很可能是异步的,回调将在其他地方定义,因此最好将数据作为参数传入

    function a() { 
      var something = 10; 
    
      (function() { // This is a closure
        console.log(something); // The same `something` defined above
      }());
    } 
    
    a();
    
    有闭包是很方便的,但是如果您正在编写一个依赖于回调的函数,它很可能是异步的,回调将在其他地方定义,因此最好将数据作为参数传入

    function a() { 
      var something = 10; 
    
      (function() { // This is a closure
        console.log(something); // The same `something` defined above
      }());
    } 
    
    a();
    
    第二对代码段 调用函数时,会传入一个隐式函数。调用
    clientData.setUserName()
    大致相当于说
    clientData.setUserName.call(clientData)
    。传入的第一个参数是将分配给此
    的对象。但是,如果您将函数
    clientData.setUserName
    作为回调传递给某个对象,并调用该函数,则更等同于说
    clientData.setUserName.call(this)
    ,其中
    this
    不再是
    clientData
    (除非您在
    clientData
    上调用另一个函数)。如果
    未被覆盖,它将引用全局对象。在web浏览器中,这将是
    窗口
    。一种可能的解决方案是,在调用函数时,使用覆盖此
    将是什么:

    function getUserInput(firstName, lastName, callback) {
      callback(firstName, lastName);
    }
    
    getUserInput('viet','nguyen',clientData.setUserName.bind(clientData));
    
    另一种可能的解决方案是在回调中传入
    clientData
    ,尽管这是一种不太可靠的解决方案,因为这意味着
    getUserInput
    将始终使用
    clientData
    ,而不是让调用者决定:

    function getUserInput(firstName, lastName, callback) {
      callback.call(clientData, firstName, lastName);
    }
    
    getUserInput('viet','nguyen',clientData.setUserName);
    

    @MarcosPérezGude他要求的是解释,而不是代码审查。@MarcosPérezGude在帮助中心的主题中特别列出,在非主题问题的描述下:“故障排除、调试或理解代码片段”(我的重点)。这个问题对于代码审查来说是特别离题的。@MarcosPérezGude不!不不关于理解代码片段的询问在代码评审中被列为非主题。没有含糊不清的地方。请停止混淆操作。其中一个最接近的原因是:“问题必须涉及您拥有或维护的真实代码。伪代码、假设代码或存根代码应该被具体实现所取代。寻求对其他人代码的解释的问题也离题。”@MarcosPérezGude这是真的,如果OP需要代码的反馈。就这个问题而言,OP想要对代码进行解释,但这是不一样的。事实是:这个问题将在代码审查时立即结束。@MarcosPérezGude这个问题对于程序员来说并不合适——它将很快被否决并在那里结束,请参见。建议阅读:。请不要推荐你不熟悉的网站谢谢你的帮助,我知道我可以使用bind或call,但我想做一点改变,就是这样,你说你对第二对