如何通过“setInterval”有效地传递范围

发布于 2024-09-14 06:44:11 字数 351 浏览 7 评论 0原文

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

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

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

I'm currently wondering if there is a better solution than passing this scope to the lambda-function via the parameter 'e' and then passing it to 'funkyFunction' using call()-method

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

(Minor question aside: I'd been reading something about memory-leaks in javascript. How does the lambda-function affect my memory? Is it better to define it first like var i = function(e)... and then passing it as a parameter to setInterval?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

℉絮湮 2024-09-21 06:44:11

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

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

我的情况是我的代码位于类方法内,我需要保持正确的范围,因为我不希望“this”绑定解析为当前窗口。

例如。我想使用 setInterval 从 MyClass.init 运行 MyClass.animate,因此我将此范围保持代码放入 MyClass.init 中

My situation may have been a bit different, but here's what I did:

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

My scenario was that my code was inside a class method and I needed to keep correct scope as I didn't want the 'this' binding to resolve to the current window.

eg. I wanted to run MyClass.animate from MyClass.init using setInterval so I put this scope-keep code into MyClass.init

成熟的代价 2024-09-21 06:44:11

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

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

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

You can use native bind function.

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

paste this example in the console to see the result

独享拥抱 2024-09-21 06:44:11

简单地依赖外部作用域定义的变量有什么问题?

(function() { 

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

})();

What's wrong with simply relying on the outer-scope defined variable?

(function() { 

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

})();
迷离° 2024-09-21 06:44:11

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

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 func 存在,该引用就不会被垃圾收集......

I had the same question, but there seems to be no built in solution, so here is a quick workaround I punched together:

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

usage:

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

This only covers the use-case where you pass an actual function, not a string of code to be executed.

As for your question about memory leaks when using this functionality: it is not so much the problem with using setInterval as it is with anonymous functions in itself.
If you use a reference to an object inside a lambda, this reference will keep the referenced object in memory for as long as the anonymous function exists. I think the function is destroyed with a call to clearInterval.

I don't think there is any benefit from assigning the function to a variable first, on the contrary, it will create another variable containing a reference that will not be garbage collected as long as the anon func exists...

诗酒趁年少 2024-09-21 06:44:11

您还可以查看 YUI Framework。它非常适合构建应用程序并且易于学习。

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

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

UPDATE 为例,

使用 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 将使用 this 引用其中的对象
  • 3° 参数:将被执行的函数。它接收作为参数传递的数组或对象作为 4° 参数
  • 5° 参数:true 如果为 true,则按提供的时间间隔连续执行,直到取消,

请参阅 http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_later

更新
不需要 $.noConflict() 因为 YUI 不以任何方式使用 $。

You may also have a look at the YUI Framework. It's fine for building applications and easy to learn.

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

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

UPDATE as example

Using YUI and jQuery (Do not forget enable $.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);

In short

  • 1º parameter: 5000 on every 5000 miliseconds, 3º parameter (a function) will be executed
  • 2º parameter: jQuery Object in which will be referenced by using this
  • 3º parameter: function which will be executed. It receives as parameter either an array or an object passed as 4º parameter
  • 5º parameter: true if true, executes continuously at supplied interval until canceled

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

UPDATE
No need for $.noConflict() because YUI does not use $ in any way.

简单气质女生网名 2024-09-21 06:44:11

有两个重要的区别需要做出。

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

There are two important distinctions to make.

1) Do you want a reference to the passed parameter so that the timeout function can track changes made to it, or do you want a clone of the passed parameter?

2) Do you want to be able to capture a reference to the timeout in case you want to cancel it? (Yes!)

// 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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文