为什么我的数据类成员不能直接使用?

时间:2011-11-28 22:16:20

标签: javascript class object scope member

我已经使用jQuery几年了,对vanilla javascript的理解非常有限。范围,对象模型,以及我在javascript中看到的许多设计模式让我感到困惑。我正在尝试实现一个最终将用于我需要编写的调度插件的类,并且我很难理解为什么存储在我的一个类成员中的数据似乎不可用。我不确定问题是否与范围或其他一些我不理解的行为有关。

我在相应位置的评论中有以下代码和2个问题。第一个问题是我的getJSON调用中的范围变通方法是否是在getJSON中处理范围问题的正确方法。我的第二个问题是为什么我不能直接访问schedule.data。

function Schedule() {
    this.year = null;
    this.month = null;
    this.day = null;

    this.start_datetime = null;
    this.start_timestamp = null;
    this.end_datetime = null;
    this.end_timestamp = null;

    this.data = [];

    return this;
}

Schedule.prototype.init = function() {
    var url = '/tripsys/new_admin/employee_schedule/get_employee_schedule_data/' + this.start_timestamp + '/' + this.end_timestamp;
    var self = this; // 1. trying to work around scope issues.  Is this the correct way to handle the scope problems here?
    $.getJSON(url, function(data) {
        self.data = data;
    }); 
}

var schedule = new Schedule();

$(document).ready(function() {
    schedule.year = $('#year').text();
    schedule.month = $('#month').text();
    schedule.day = $('#day').text();
    schedule.start_datetime = new Date(schedule.year, schedule.month - 1, schedule.day);
    schedule.start_timestamp = Math.round(schedule.start_datetime.getTime() / 1000);
    schedule.end_datetime = new Date(schedule.year, schedule.month - 1, schedule.day, 23, 59, 59);
    schedule.end_timestamp = Math.round(schedule.end_datetime.getTime() / 1000);

    schedule.init();
    console.log(schedule); // if I log the whole schedule object the data that I expect to be in the "data" member is there
    console.log(schedule.data); // 2. why is the data that I expect to be in the "data" member not there when I access schedule.data directly?
});

感谢您的见解。

4 个答案:

答案 0 :(得分:1)

这可能是因为在这一行schedule.init();中,当你执行console.log(schedule.data);时,它会进行一个尚未完成的ajax调用。 Ajax调用是异步的。调用它们只会启动网络操作,然后立即返回。在调用成功处理函数之前,它们不会完成(并且在分配self.data时)。

因此,如果要查看在.init()函数中获取的调度对象的数据,则必须等到该ajax调用完成或对完成函数中的数据执行某些操作。

答案 1 :(得分:1)

第一点是正确的,因为你需要保存this引用,因为当jQuery调用内部函数时,函数内的this将引用ajax对象

在第二条评论中,您在ajax请求完成之前记录schedule.data。您在登录schedule.data时可以看到schedule,因为当您在Google Chrome中记录对象时,手动"展开"后会检索对象属性。 chrome控制台中的对象。当您手动"展开"它,当时请求已经完成。

您可以像这样重现:

var a = {};
console.log(a); //do not "expand" the object properties yet
console.log(a.property); //undefined
a.property = "value";
//"expand" the already logged object and it will have "value"

答案 2 :(得分:1)

  1. 是的,虽然它不是范围问题,但它使用变量范围来解决上下文问题。

  2. 要访问schedule.data,您需要等到数据到达。换句话说,将console.log代码放在回调中。

答案 3 :(得分:1)

问题是在记录对象之前没有返回ajax调用。如果要使ajax调用同步并且init函数在记录之前获得结果,请在ajax jQuery调用上使用async参数:

$.ajax({  
    url: url,  
    dataType: 'json',  
    async: false,  
    success: function(data){  
      self.data = data;
      console.log(data);
    }  
});