Как офигенно передать прицел через "setInterval" - PullRequest
4 голосов
/ 15 августа 2010

В настоящее время мне интересно, есть ли лучшее решение, чем передача этой области видимости в лямбда-функцию через параметр 'e' и затем ее передача в функцию funkyFunction с помощьюcall () - метод

setInterval(function(e){e.funkyFunction.call(e)}, speed, this)

(Небольшой вопрос в стороне: я читал кое-что о утечках памяти в javascript. Как lambda-функция влияет на мою память? Лучше определить ее сначала какvar i = function(e)..., а затем передать его в качестве параметра setInterval?)

Ответы [ 6 ]

9 голосов
/ 03 февраля 2011

Моя ситуация, возможно, была немного другой, но вот что я сделал:

var self = this;
setInterval(function() { self.func() }, 50);

Мой сценарий состоял в том, что мой код был внутри метода класса, и мне нужно было сохранить правильную область видимости, поскольку я этого не делалхотите, чтобы привязка 'this' разрешалась в текущем окне.

например.Я хотел запустить MyClass.animate из MyClass.init, используя setInterval, поэтому я поместил этот код сохранения содержания в MyClass.init

.
5 голосов
/ 06 января 2014

Вы можете использовать встроенную функцию связывания.

function Loop() {
    this.name = 'some name for test';
    setInterval( (function(){//wrap the function as object
        //after bind, "this" is loop refference
        console.log(this);
    }).bind(this), 1000 );// bind the object to this (this is Loop refference)
}

var loop = new Loop();

вставьте этот пример в консоль, чтобы увидеть результат

4 голосов
/ 15 августа 2010

Что плохого в том, чтобы просто полагаться на переменную, определенную во внешней области видимости?

(function() { 

    var x = {};
    setInterval(function() {
       funkyFunction.call(x)
    }, speed);

})();
1 голос
/ 14 августа 2013

Вы также можете взглянуть на YUI Framework.Он отлично подходит для создания приложений и прост в освоении.

YUI2: YAHOO.lang.later(when, scope, fn, args, periodic);

YUI3: Y.later(when, scope, fn, args, periodic);

ОБНОВЛЕНИЕ в качестве примера

Использование YUI и jQuery (Не забудьте включить $ .noConflict ())

var jQuerySelector = jQuery("div[class^='form-field-']");

jQuerySelector.hide();
jQuery(jQuerySelector[0]).show();


YAHOO.lang.later(5000, jQuery, function(jQuerySelector) {
    if((!(this.index)) || (this.index == (jQuerySelector.length))) {
        this.index = 0;
    }

    jQuerySelector.hide();

    this(jQuerySelector[this.index++]).show();
}, jQuerySelector, true);

Короче говоря

  • 1º параметр: 5000 каждые 5000 миллисекунд, 3º параметр (функция) будет выполняться
  • 2ºпараметр: jQuery Объект, на который будет ссылаться с помощью этот
  • 3º параметр: функция , которая будет выполнена.Он получает в качестве параметра массив или объект, переданный как параметр 4º
  • 5º параметр: true , если true, выполняется непрерывно с предоставленным интервалом до отмены

см.http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_later

ОБНОВЛЕНИЕ Нет необходимости в $ .noConflict (), потому что YUI никак не использует $.

1 голос
/ 12 августа 2013

У меня был тот же вопрос, но, кажется, нет встроенного решения, поэтому вот быстрый обходной путь, который я пробил вместе:

function setScopedInterval(func, millis, scope) {
    return setInterval(function () {
        func.apply(scope);
    }, millis);
}

использование:

function MyClass() {
    this.timer = null;
    this.myFunc = function() { console.log('do some stuff'); };
    this.run = function() {
        this.timer = setScopedInterval(function () { this.myFunc(); }, 1000, this);
    };
    this.stop = function() { clearInterval(this.timer); };
}
var instance = new MyClass();
instance.run(); // will log to console every second
// until this line is called
instance.stop();

Это относится только к случаю использования, когда вы передаете фактическую функцию, а не строку кода для выполнения.

Что касается вашего вопроса об утечках памяти при использовании этой функциональности: проблема не только в использовании setInterval, сколько в самих анонимных функциях. Если вы используете ссылку на объект внутри лямбды, эта ссылка будет хранить указанный объект в памяти до тех пор, пока существует анонимная функция. Я думаю, что функция уничтожается при вызове clearInterval.

Я не думаю, что есть какая-то польза от присвоения функции сначала переменной, напротив, она создаст другую переменную, содержащую ссылку, которая не будет собираться мусором, пока существует функция anon ...

0 голосов
/ 01 декабря 2014

Необходимо сделать два важных различия.

1) Хотите ли вы ссылку на переданный параметр, чтобы функция тайм-аута могла отслеживать изменения, внесенные в него, или вы хотите клонировать переданный параметр??

2) Хотите ли вы получить ссылку на тайм-аут в случае, если вы хотите отменить его?(Да!)

// Normal setTimeout: retains a reference to `test` and returns the bad value
var test = 'test: good';
var timer = setTimeout(function() { console.log(test); }, 1000);
test = 'test: bad';

// Test2 receives a clone of `test2` and returns the good value, but does so right away, not on a timeout
var test2 = 'test2: good';
var timer2 = setTimeout((function() { console.log(test2); })(test2), 1000);
test2 = 'test2: bad';

// Test3 receives a clone of `test3` and returns the good value, but doesn't return a reference to the timeout, and can't be canceled
var test3 = 'test3: good';
var timer3 = function(test3) { setTimeout(function() { console.log(test3); }, 1000); }(test3);
test3 = 'test3: bad';

// Test4 receives a clone of `test4` and returns the good value, and correctly returns timeout reference
var test4 = 'test4: good';
var timer4 = function(test4) { return setTimeout(function() { console.log(test4); }, 1000); }(test4);
test4 = 'test4: bad';

// Test5 retains a reference to `test5` and returns the bad value
var test5 = 'test5: good';
var timer5 = setTimeout((function() { console.log(test5); }).bind(test5), 1000);
test5 = 'test5: bad';

// Did we capture references to the timeouts?
console.log(typeof timer);
console.log(typeof timer2);
console.log(typeof timer3);
console.log(typeof timer4);
console.log(typeof timer5);
...