Методы класса JavaScript - PullRequest
       21

Методы класса JavaScript

1 голос
/ 09 июня 2011

Я определил свой класс следующим образом:

function Slot(slot, maxSpeed, timer) {
this.slot = slot;
this.speed = 0;
this.maxSpeed = maxSpeed;
this.timer = timer;
this.interval = null;

this.go = function() {
    var $slot = $(this.slot);
    console.log(this.slot);
    $slot.addClass('motion');
    $slot.spStart();

    this.interval = window.setInterval(function() {
        var step = Math.floor(Math.random() * ((this.speed / 100) * 25)) + 1;
        if (this.speed < (this.maxSpeed / 2)) {
            this.speed += step;
        }

        if (this.speed >= (this.maxSpeed / 2)) {
            this.speed -= step;
        }
        console.log(this.slot);
        $slot.spSpeed(this.speed);
    }, timer);
};

$(this.slot).pan({ fps: '30', dir: 'down' });
$(this.slot).spStop();
}

Первый console.log возвращает ожидаемое значение, но как только я попадаю в функцию setInterval, все переменные (this.slot, this.speed)все неопределено?Даже если я все еще в их пределах ...

Ответы [ 5 ]

2 голосов
/ 09 июня 2011

Scoping - это немного странно, чтобы привыкнуть в Javascript, даже страннее, когда вы начинаете использовать setInterval и setTimeout.

В вашем случае, это внутри интервала относится к самой анонимной функции.Вы можете назначить 'this' другой переменной вне анонимной функции:

var self = this;
this.interval = window.setInterval(function(){ /* use self here instead of this*/}

или вызвать функцию объекта на шаге интервала:

this.interval = window.setInterval(this.callback, timer);
1 голос
/ 09 июня 2011

Когда setInterval () выполняет ваш метод обратного вызова, он делает это вне контекста вашего класса, поэтому «this» не относится к вашему классу.Вы должны передать ссылку своего класса «this» в качестве аргумента обратного вызова.

var that = this;
setInterval(function() {
  that.someVar ...
  that.someMethod() ...
});
1 голос
/ 09 июня 2011

это просто, поставь

var self = this;

в this.go, и везде в функции таймера замените это на self -

this.go = function() {
     var $slot = $(this.slot);
     console.log(this.slot);
     $slot.addClass('motion');
     $slot.spStart();
     var self = this;

     this.interval = window.setInterval(function() {
         var step = Math.floor(Math.random() * ((self.speed / 100) * 25)) + 1;
         if (self.speed < (self.maxSpeed / 2)) {
             self.speed += step;
         }

         if (self.speed >= (self.maxSpeed / 2)) {
             self.speed -= step;
         }
         console.log(self.slot);
         $slot.spSpeed(self.speed);
     }, timer);
 };

`

1 голос
/ 09 июня 2011

Нет, потому что this относится к чему-то еще внутри setInterval. Вам нужно определить статическую копию, например:

this.go = function() {
    var $slot = $(this.slot);
    console.log(this.slot);
    $slot.addClass('motion');
    $slot.spStart();

    var that = this;

    this.interval = window.setInterval(function() {
        var step = Math.floor(Math.random() * ((that.speed / 100) * 25)) + 1;
        if (that.speed < (that.maxSpeed / 2)) {
            that.speed += step;
        }

        if (that.speed >= (that.maxSpeed / 2)) {
            that.speed -= step;
        }
        console.log(that.slot);
        $slot.spSpeed(that.speed);
    }, timer);
};
1 голос
/ 09 июня 2011

Ваше утверждение "Хотя я все еще в их поле зрения" неверно.Переменная 'this' всегда задает функциональный контекст, в котором функция выполняется , а не в которой она определена.В этом случае функция внутри setInterval выполняется из области окна, и «this» фактически является окном.

Чтобы обойти эту проблему, я рекомендую использовать замыкание: (обратите внимание на добавление 'переменная self и замена вложенных вызовов this на self 100 *

function Slot(slot, maxSpeed, timer) {
    var self = this;
    this.slot = slot;
    this.speed = 0;
    this.maxSpeed = maxSpeed;
    this.timer = timer;
    this.interval = null;

    this.go = function() {
        var $slot = $(self.slot);
        console.log(self.slot);
        $slot.addClass('motion');
        $slot.spStart();

        self.interval = window.setInterval(function() {
            var step = Math.floor(Math.random() * ((self.speed / 100) * 25)) + 1;
            if (self.speed < (self.maxSpeed / 2)) {
                self.speed += step;
            }

            if (self.speed >= self.maxSpeed / 2)) {
                self.speed -= step;
            }
            console.log(self.slot);
            $slot.spSpeed(self.speed);
        }, timer);
    };

    $(self.slot).pan({ fps: '30', dir: 'down' });
    $(self.slot).spStop();
}
...