javascript 如何通过“setInterval”快速传递范围
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3488591/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to kick-ass pass scope through "setInterval"
提问by PenthousePauper
I'm currently wondering if there is a better solution than passing thisscope to the lambda-function via the parameter 'e'and then passing it to 'funkyFunction' using call()-method
我目前想知道是否有比通过参数“e”将此范围传递给 lambda 函数然后使用 call() 方法将其传递给“funkyFunction”更好的解决方案
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?)
(抛开小问题:我一直在阅读有关 javascript 中内存泄漏的一些内容。lambda 函数如何影响我的内存?最好先定义它var i = function(e)...,然后将其作为参数传递给 setInterval?)
采纳答案by meder omuraliev
What's wrong with simply relying on the outer-scope defined variable?
仅仅依赖外部作用域定义的变量有什么问题?
(function() {
var x = {};
setInterval(function() {
funkyFunction.call(x)
}, speed);
})();
回答by Hymansonkr
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.
我的情况是我的代码在一个类方法中,我需要保持正确的范围,因为我不希望“this”绑定解析为当前窗口。
eg. I wanted to run MyClass.animate from MyClass.init using setInterval so I put this scope-keep code into MyClass.init
例如。我想使用 setInterval 从 MyClass.init 运行 MyClass.animate 所以我把这个范围保持代码放入 MyClass.init
回答by CORSAIR
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
将此示例粘贴到控制台中以查看结果
回答by NDM
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 setIntervalas 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.
至于您在使用此功能时有关内存泄漏的问题:与其说是使用问题,setInterval不如说是使用匿名函数本身。如果您在 lambda 中使用对对象的引用,则只要匿名函数存在,此引用就会将引用的对象保留在内存中。我认为该函数通过调用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...
我认为首先将函数分配给变量没有任何好处,相反,它会创建另一个包含引用的变量,只要 anon func 存在,该变量就不会被垃圾收集......
回答by PapaKai
You may also have a look at the YUIFramework. It's fine for building applications and easy to learn.
您也可以查看YUIFramework. 它非常适合构建应用程序并且易于学习。
YUI2: YAHOO.lang.later(when, scope, fn, args, periodic);
YUI3: Y.later(when, scope, fn, args, periodic);
UPDATEas example
以更新为例
Using YUI and jQuery (Do not forget enable $.noConflict())
使用 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);
In short
简而言之
- 1o parameter: 5000on every 5000 miliseconds, 3o parameter (a function) will be executed
- 2o parameter: jQueryObject in which will be referenced by using this
- 3o parameter: functionwhich will be executed. It receives as parameter either an array or an object passed as 4o parameter
- 5o parameter: trueif true, executes continuously at supplied interval until canceled
- 1O参数:5000上每5000毫秒,10-30参数(的函数)将被执行
- 2o 参数:jQuery对象,将在其中使用this
- 3o 参数:将要执行的函数。它接收作为参数的数组或作为 4o 参数传递的对象
- 5o 参数:true如果为 true,则以提供的时间间隔连续执行直到取消
see http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_later
见http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_later
UPDATENo need for $.noConflict() because YUI does not use $ in any way.
更新不需要 $.noConflict() 因为 YUI 不以任何方式使用 $。
回答by Tyler V.
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?
1) 您是否需要对传递参数的引用,以便超时函数可以跟踪对其所做的更改,还是需要传递参数的副本?
2) Do you want to be able to capture a reference to the timeout in case you want to cancel it? (Yes!)
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);

