如何通过“setInterval”传递范围

时间:2010-08-15 18:10:59

标签: javascript memory-leaks scope setinterval lambda

我目前想知道是否有更好的解决方案,而不是通过参数'e'范围传递给lambda函数,然后将其传递给'funkyFunction '使用call() - 方法

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

(除了小问题:我一直在阅读有关javascript中内存泄漏的内容.lambda函数如何影响我的内存?最好先定义它,如var i = function(e)...,然后将其作为setInterval的参数?)

6 个答案:

答案 0 :(得分:9)

我的情况可能有点不同,但这就是我所做的:

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

我的情况是我的代码在一个类方法中,我需要保持正确的范围,因为我不希望'this'绑定解析到当前窗口。

例如。我想使用setInterval从MyClass.init运行MyClass.animate,所以我将这个scope-keep代码放入MyClass.init

答案 1 :(得分:5)

您可以使用本机绑定功能。

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();

将此示例粘贴到控制台中以查看结果

答案 2 :(得分:4)

简单地依赖外部范围定义的变量有什么问题?

(function() { 

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

})();

答案 3 :(得分:1)

我有同样的问题,但似乎没有内置的解决方案,所以这是一个快速的解决方法,我打了一拳:

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并不是因为它本身就是匿名函数。 如果使用对lambda内对象的引用,则只要匿名函数存在,此引用就会将引用的对象保留在内存中。我认为通过调用clearInterval来破坏该功能。

我认为首先将函数赋值给变量没有任何好处,相反,它会创建另一个包含引用的变量,只要anon函数存在就不会被垃圾收集... < / p>

答案 4 :(得分:1)

您还可以查看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不以任何方式使用$。

答案 5 :(得分:0)

要做出两个重要的区别。

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);