Javascript中的变量范围

时间:2010-10-05 13:33:11

标签: javascript jquery ajax drupal

在这种情况下,我无法理解'this'的范围。我可以调用这些函数中的每一个,例如:this.startTracking();从时间跟踪器切换对象内。但是,当我尝试执行代码时:Drupal.timeTracker.prototype.stopTracking();它丢失了所有变量范围,我的GET请求变得未定义。如何启动stopTracking()onbeforeunload?

    Drupal.behaviors.dynamicTimeTracker = function (context) {
  $('form.node-time-tracker', context).each(function () {
    new Drupal.timeTracker(this);
  });
};

/**
 * A time tracker switch object
 */
Drupal.timeTracker = function (form) {
  var tracker = this;
  this.form = form;
  this.nid = $('#'+ form.id +' input[name="nid"]').attr('value');
  this.uid = $('#'+ form.id +' input[name="uid"]').attr('value');
  this.button = $('#'+ form.id +' input[type="submit"]');
  this.url = Drupal.settings.time_tracker.url + '/' + this.nid + '/' + this.uid;
  this.counter = $('#'+ form.id +' .counter');

  this.initialize(); // TODO: make sure this function is called regularly to make sure trackers are in synch
  this.startTracking();
  $(window).bind('beforeunload', function() {
    Drupal.timeTracker.prototype.stopTracking(); // need help here
  });
};

/**
 * Initialize the time tracker
 */
Drupal.timeTracker.prototype.initialize = function () {
  var tracker = this;

  $.ajax({
    type: "GET",
    url: tracker.url,
    dataType: 'json',
    success: function (status) {
      $(tracker.counter).countdown({compact:true, since:-status['time']}).countdown('resume');

      if (status['status'] == 'ongoing') {
        $(tracker.button).toggle(
          function() {
            tracker.stopTracking();
            return false;
          },
          function() {
            tracker.startTracking();
            return false;
          }
        );
        $(tracker.counter).countdown('resume');
        $(tracker.button).val(Drupal.t('Stop'));
        $(tracker.form).removeClass('node-time-tracker-start').addClass('node-time-tracker-stop');
      }
      else {
        $(tracker.button).toggle(
          function() {
            tracker.startTracking();
            return false;
          },
          function() {
            tracker.stopTracking();
            return false;
          }
        );
        $(tracker.counter).countdown('pause');
        $(tracker.button).val(Drupal.t('Start'));
        $(tracker.form).removeClass('node-time-tracker-stop').addClass('node-time-tracker-start');
      } 
    },
    error: function (xmlhttp) {
      alert(Drupal.ahahError(xmlhttp, tracker.startURL));
    }
  });
};

/**
 * Starts time tracking
 */
Drupal.timeTracker.prototype.startTracking = function () {
  var tracker = this;

  // Ajax GET request for starting time tracker
  $.ajax({
    type: "GET",
    url: tracker.url + '/start',
    dataType: 'json',
    success: function (status) {
      $(tracker.counter).countdown('change', {since: -status['time']}).countdown('resume');
      $(tracker.button).val(Drupal.t('Stop'));
      $(tracker.form).removeClass('node-time-tracker-start').addClass('node-time-tracker-stop');
    },
    error: function (xmlhttp) {
      alert(Drupal.ahahError(xmlhttp, tracker.startURL));
    }
  });
};

/**
 * Stops time tracking
 */
Drupal.timeTracker.prototype.stopTracking = function () {
  var tracker = this;

  // Ajax GET request for stopping time tracker
  $.ajax({
    type: "GET",
    url: tracker.url + '/stop',
    dataType: 'json',
    success: function (status) {
      $(tracker.counter).countdown('change', {since: -status['time']}).countdown('pause');
      $(tracker.button).val(Drupal.t('Start'));
      $(tracker.form).removeClass('node-time-tracker-stop').addClass('node-time-tracker-start');
    },
    error: function (xmlhttp) {
      alert(Drupal.ahahError(xmlhttp, tracker.startURL));
    }
  });
};

3 个答案:

答案 0 :(得分:1)

我会拿出一小段代码:

this.startTracking();
$(window).bind('beforeunload', function() {
  // this is defined by the above function definition
  tracker.stopTracking();
});

你的问题是,当你在其中创建绑定函数this时,会引用$(window),所以你需要创建一个这样的副本,以便能够在其中引用它新功能。

答案 1 :(得分:0)

googletorp的答案应该有效,但只是一个快速的说明:

我相信你遇到的问题是因为你试图打电话:

Drupal.timeTracker.prototype.stopTracking();

相反,我认为它应该是:

Drupal.timeTracker.stopTracking();

我不相信你应该在原型上调用函数,而是调用你修改过原型的对象。

答案 2 :(得分:0)

当您致电new Drupal.timeTracker(this)时,会创建一个新对象。该对象继承自Drupal.timeTracker.prototype。在该对象的方法内部,this被设置为对象本身。 Drupal.timeTracker.prototype不是对象,而只是一个模板,可以从中创建对象的新实例;就像一个千篇一律的刀具,吃起来不是很好。最重要的是,你的实际计时器的内部状态都不存在。

当你致电Drupal.timeTracker.prototype.stopTracking时,它会在模板上调用,而不是真实对象。如果你致电tracker.stopTracking(),你会没事的。您无法致电this.stopTracking(),因为当您要致电stopTracking时,您处于onbeforeunload的事件处理程序中,因此您的this将是{{1}对象。