[英]Scope in generated Callback function
我有一个用于事件监听器的生成器函数生成回调函数:
function createCallback(counter){
return function(){
counter++;
}
}
回调应该只计算单击按钮的频率。 让我们生成两个函数:
var counter1 = 0;
var counter2 = 0;
var callback1 = createCallback(counter1);
var callback2 = createCallback(counter2);
并将它们注册为侦听器:
button1.addEventListener("click", callback1);
button2.addEventListener("click", callback2);
现在我需要一个重置功能:
function reset(){
counter1 = 0;
counter2 = 0;
}
我曾期望,生成器函数将对全局计数器的引用传递到生成的回调函数中,并且回调函数将修改全局变量。 但是,正如我从重置功能中学到的那样,它们不是。
范围存在问题,但我不明白。
createCallback
函数的参数counter
没有作为引用传递给生成的函数。 编辑
您可以使用一个对象来存储计数器并在以下位置传递属性名称:
const counters = {
a: 0,
b: 0
};
function createCallback(counterName){
return function(){
counters[counterName]++;
}
}
button1.addEventListener("click", createCallback("a"));
button2.addEventListener("click", createCallback("b"));
function reset(){
counters.a = 0;
counters.b = 0;
}
(如果不需要单独的名称,请改用带有索引的数组)
另一种选择是在同一变量上为不同的功能创建多个闭包,并将其保留在每个计数器的一个对象中。 这就是面向对象的方式:
function createCounter() {
var counter = 0;
return {
getCount() {
return counter;
},
reset() {
counter = 0;
},
increment() {
counter++;
}
};
}
const counter1 = createCounter();
const counter2 = createCounter();
button1.addEventListener("click", counter1.increment);
button2.addEventListener("click", counter2.increment);
function reset(){
counter1.reset();
counter2.reset();
}
(同样,如果需要任意多个,请使用计数器数组而不是多个单独命名的变量)
JS中的对象通过引用(实际上是通过引用值)进行粘贴,因此可以正常工作( setTimeouts
用于模拟回调)
function createCallback(counter){ return function(){ counter.count++; } } function reset(){ counter1.count = 0; counter2.count = 0; } var counter1 = {count: 0}; var counter2 = {count: 0}; var callback1 = createCallback(counter1); var callback2 = createCallback(counter2); setTimeout(function(){ callback1(); document.getElementById('result').innerHTML += counter1.count + ' '; }, 1000); setTimeout(function(){ callback1(); document.getElementById('result').innerHTML += counter1.count + ' '; }, 2000); setTimeout(function(){ callback1(); document.getElementById('result').innerHTML += counter1.count + ' '; }, 3000); setTimeout(function(){ reset(); document.getElementById('result').innerHTML += counter1.count + ' '; }, 4000);
<div id="result"></div>
在Javascript中,原始类型变量(例如字符串和数字)始终按值传递。 因此,您可以使用对象而不是原始变量:
将全局变量嵌入对象内:
var myCounterObj = {
counter1: 0,
counter2: 0
}
通过以下方式更改您的回调定义:
function createCallback(counter, name) {
return function() {
counter[name]++;
console.log("My counter is: " + counter[name]);
}
}
然后创建回调变量:
var callback1 = createCallback(myCounterObj, 'counter1');
var callback2 = createCallback(myCounterObj, 'counter2');
最后更改重置功能:
function reset() {
myCounterObj.counter1 = 0;
myCounterObj.counter2 = 0;
}
希望这可以帮助!
变量counter
( counter1
, counter2
)按值传递,按引用传递bot。 为了使其工作,应将变量更改为对象:
var counter1 = {"value": 0};
var counter2 = {"value": 0};
这些可以传递到生成器函数中。 增量必须相应地更改:
function generate(counter){
return function(){
counter.value++;
}
}
以及重置功能:
function reset(){
counter1.value = 0;
counter2.value = 0;
}
现在可以了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.