确定Javascript函数范围问题

时间:2011-05-28 06:15:00

标签: javascript jquery function scope

很明显我不明白函数在Javascript中的作用域。这是最新的例子:

function riseData() { 
    var jsonResult;
    $.ajax({
        success: function(data, textStatus, jqXHR){
            jsonResult = jqXHR.responseText;
            alert("Inside: " + jsonResult);
        },          
        error: function (jqXHR, textStatus, errorThrown) {  
            $('#errLog').append('<br>Status: ' + qXHR.statusText);                  
        }
    });
    return jsonResult;
}

$(document).ready(function(){
    var intervalID = setInterval('UTCclock()',100); 
    alert("Outside: " + riseData());                            
});

当我执行此操作时,“Inside”警报功能正常,但“Outside”警报显示“undefined”,即使roseData()显然只提前几行定义。代码中前面有一个$ .ajaxSetup,它定义了ajax调用的参数。 ajax调用成功返回“Inside”警报中的请求数据。

我只是没有丝毫知道如何将必要的数据(jqXHR.responseText)提供给脚本的其他部分。

任何人都可以指点我的“Javascript Scoping for Dummies”如何解决这个问题?

2 个答案:

答案 0 :(得分:5)

你的例子范围很好。您的问题是您不了解JavaScript主要是异步的含义。

让我通过你的例子向你展示。

  1. 您的文档就绪处理程序运行。
  2. 它会调用riseData
  3. riseData声明变量jsonResult
  4. riseData调用$.ajax,它会安排完成一个AJAX请求,但响应会在稍后发生。
  5. 由于$.ajax通常是非阻止/异步的,riseData会继续并返回jsonResult。由于尚未完成jsonResult,因为AJAX请求尚未完成,因此会返回默认值undefined
  6. 在文档就绪处理程序中,您最终得到alert("Outside: "+undefined);
  7. 事件循环到几毫秒后,会发生这种情况:

    1. AJAX请求已完成。 jQuery将此转发给您的回调。
    2. jsonResult已设置,但riseData已返回。
    3. 在文档就绪处理程序已经提醒alert之后,riseData内部undefined警报带有新数据。
    4. 这个问题有两个解决方案。第一种解决方案很简单,但往往会导致更糟糕的用户体验。此解决方案是将async: false选项添加到$.ajax。这会使$.ajax阻止并冻结浏览器。

      第二种解决方案是对几乎所有东西都采用异步风格。这意味着让riseData接受回调并在AJAX响应处理程序中调用它。这是使用此方法转换的代码:

      function riseData(callback) { 
          $.ajax({
              success: function(data, textStatus, jqXHR){
                  var jsonResult = jqXHR.responseText;
                  alert("Inside: " + jsonResult);
                  callback(jsonResult);
              },          
              error: function (jqXHR, textStatus, errorThrown) {  
                  $('#errLog').append('<br>Status: ' + qXHR.statusText);                  
              }
          });
      }
      
      $(document).ready(function(){
          //var intervalID = setInterval('UTCclock()',100); 
          // Unrelated, but it's better to pass a
          // function into setInterval than a string.
          var intervalID = setInterval(UTCclock, 100);
          riseData(function(jsonResult) {
              alert("Outside: " + jsonResult);
          });
      });
      

答案 1 :(得分:0)

这只是部分范围问题。您的ajax调用是异步的,因此riseData()函数在执行ajax调用之前返回一个值。尝试在方法之外设置变量。

var jsonResult;

function riseData() { 

    $.ajax({
...

jsonResult不仅应该在riseData()中可用,而且还应该可用。但是,您仍然会遇到填充时的确切问题。

更多解释的链接:

What is the scope of variables in JavaScript?