【问题标题】:Can't set scoped variable in $.post callback无法在 $.post 回调中设置作用域变量
【发布时间】:2015-02-01 08:49:33
【问题描述】:

我有以下类型的结构:

(function(){

var objects = [];

$('button.one').on('click', function(){

  fetchObjects = function(objects) {
    $.post("/fetchObjects")
      .done(function(data){
        objects = data;
        console.log(objects.length);
      });
  }
  fetchObjects(objects)

});

$('button.two').on('click', function(){
  console.log(objects.length);
});

})();

你可以看到我有一个变量objects,它是这个函数的本地变量。最初它是空的。当我单击button.one 时,我希望使用某个ajax 请求的返回值填充objects。它似乎可以工作,但是当单击button.two 时,objects 变量仍然是一个空数组。

为什么 jQuery 回调中没有 objects

我也尝试过这种方法,但结果相同:

function callback(data) {
  facilities = data
}

$.post("/fetchObjects")
.done(function(data){
  callback(data);
});

我在这里缺少什么?请不要告诉我将“对象”设为全局。

【问题讨论】:

  • objects = data 不会改变原来的objects 变量。
  • 为什么将对象作为参数传递?直接访问不是更方便吗?
  • objects = data 没有直接访问它?如果没有,我如何直接访问它? @Juhana 我知道。那有什么办法呢?

标签: javascript jquery asynchronous callback scope


【解决方案1】:

我不知道您为什么将对象作为参数传递。我认为以下应该可以正常工作。如果您想实现其他目标,请告诉我。

(function(){

var objects = [];

$('button.one').on('click', function(){

  fetchObjects = function() {
    $.post("/fetchObjects")
      .done(function(data){
        objects = data;
        console.log(objects.length);
      });
  }
  fetchObjects()

});

$('button.two').on('click', function(){
  console.log(objects.length);
});

})();

【讨论】:

    【解决方案2】:

    让我们稍微简化一下代码。你基本上有这个:

    var objects = [];
    
    fetchObjects = function(innerObjects) {
      var data = ['a','b'];
      innerObjects = data;
      console.log(innerObjects.length);
    };
    
    fetchObjects(objects);
    console.log(objects);

    (为了清楚起见,我更改了另一个 objects 变量的名称;即使名称相同,问题也是一样的。)

    当您调用该函数时,innerObjects 包含对 objects 的引用,因此修改它也会更改原始数组。但是当你这样做时

    innerObjects = data;
    

    现在,而不是 修改 数组,您将引用替换为其他内容。 innerObjects“指向”data 而不是objects,原始变量保持不变。

    要使其工作,您需要遍历data 数组(假设它始终是一个数组)并将内容一一分配给objects 引用。这样,您将保留原始引用并修改原始数组。

    var objects = [];
    
    fetchObjects = function(innerObjects) {
      var data = ['a','b'];
     
      for( var i = 0; i < data.length; i++ ) {
          innerObjects[i] = data[i];
      }
      console.log(innerObjects.length);
    };
    
    fetchObjects(objects);
    console.log(objects);

    或者,在您的实际代码中:

    (function(){
    
    var objects = [];
    
    $('button.one').on('click', function(){
    
      fetchObjects = function(objects) {
        $.post("/fetchObjects")
          .done(function(data){
            for( var i = 0; i < data.length; i++ ) {
              objects[i] = data[i];
            }
            console.log(objects.length);
          });
      }
      fetchObjects(objects)
    
    });
    
    $('button.two').on('click', function(){
      console.log(objects.length);
    });
    
    })();
    

    【讨论】:

    • 为什么不直接从方法中访问对象?您不需要循环也不需要将对象作为参数传递...
    • @acontell 该函数现在适用于传递给它的任何数组。如果您删除参数和循环,那么它将仅适用于一个硬编码变量。
    • 这就是我感到困惑的地方。而不是使用innerObjects,为什么我不能直接说objects = data?因为那时我会认为我正在用来自data 的东西替换objects 变量。为什么这不起作用?
    • @Jakobud 可行,由于作用域,对象在函数中可用,您可以直接将检索数据分配给它,但不使用 Juhana 指出的参数
    • @Jakobud 您需要意识到您有 两个 变量称为objects。当您执行objects = data 时,您将局部变量 替换为data。外部变量保持不变。
    猜你喜欢
    • 2018-10-21
    • 2017-03-06
    • 2014-11-13
    • 1970-01-01
    • 1970-01-01
    • 2016-08-06
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多