如何在没有闭包的情况下对共享状态进行编程

How do I program a shared state without closures?

本文关键字:共享 状态 编程 情况下 闭包      更新时间:2023-09-26
var state = 0;
var interval = setInterval(function() { 
    // Do something depending on state
}, 1000)

由于一切都可以在没有闭包的情况下完成,这更像是一种智力练习,因为我看不到如何在没有闭包的情况下编写这样的东西。我是否通过引用将状态传递到匿名函数中?(JavaScript 不支持通过引用传递(

这是一个没有赢的答案,因为当你深入到它时,绝对没有不创建闭包的范围; 这是一个是否使用闭包以及如何使用它的问题。

闭包只是一个内部作用域,它保持对外部作用域的引用。

这样说吧:

/* global */
window.incr_id = 0;
window.tick = 0;
function nextTick () { window.tick += 1; }
window.incr_id = window.setInterval(nextTick, 1000);

这对你来说算不算结束?

从技术上讲,全局作用域相当于在其他语言的Main ()内运行,因此nextTick函数包含对外部作用域值(window(的引用,导致在值表链上遍历,从而形成"闭包"。

你可以尝试类似的东西

function nextTick () { nextTick.value += 1; }
nextTick.value = 0;

。但是,鉴于自我参考来自大括号之外,因此属于更高的范围,这算不算?

function nextTick () { arguments.callee.value += 1; }
nextTick.value = 0;

当然,这将因此阻止您在严格模式下使用此解决方案(如果您希望安全,则应使用(。

当然,你可以创建一个闭包,这不是有问题的函数,而是创建monads,这样你就可以通过组合函数增量地传递值,而不是依赖闭包引用......

当然,问题在于setInterval需要一个函数。
因此,无论你返回到哪个函数setInterval,最终函数都必须使用闭包引用,不管你是否所有的应用函数都这样做了。

如果你引用一个在当前函数范围内没有定义的函数,或者我们只是在谈论标量,函数引用算作闭包引用吗?

故事的寓意:

window.value = 1;
window.obj.value = 1;
func.value = 0;
function func () { func.value = 1; }
function func () { arguments.callee.value = 1; }

如果你愿意承认"窗口"可以被引用为不是闭包(提示,它不能(,那么前两个是有效的。

如果您愿意接受在非严格模式下运行对您的客户、受众以及您的整体健康和福祉不利,那么最后一个可能是有效的。

您可以在没有闭包的情况下做任何事情。例如,状态可以存储在一个对象中,用指定的方法来"调用函数"。但是,您将需要一个不同的setInterval()函数来采用您的方法类型,而不是现在采用的函数类型。

在 JavaScript 中,你不需要通过引用传递变量。通过在闭包中不使用var,可以影响更高级别的var

简单的例子:

var state = 0;
var interval = setInterval(function(){ 
  state++; // state increases by one every second
}, 1000);
// should console.log(4)
setTimeout(function(){console.log(state)}, 4500);

如果您这样做:

var state = 0;
var interval = setInterval(function(){
  var state = 0;
  state++; // state increases by one every second
  // state is 1 every time at this point
  // state outside closure is not affected
}, 1000);
// should console.log(0) - state refers to outside of closure
setTimeout(function(){console.log(state)}, 4500);

某种意义上说,你可以认为 JavaScript 中的每个变量都是通过引用传递的,甚至没有将它们作为参数传递。事实上,如果您确实使用变量名称作为参数,它将在您要传递给的函数中重新定义,从而不会影响更高级别的变量。

向匿名函数传递参数,可能会也可能不会执行任何操作,具体取决于情况。在setInterval()的情况下,不会将任何内容传递给您传递给它的函数。注意:

var state = 0;
var interval = setInterval(function(arg){
  var state = 0;
  state++; // state increases by one every second
  // state is 1 every time at this point
  // state outside closure is not affected
}, 1000);

var state = 0;
function what(arg){
  var state = 0;
  state++; // state increases by one every second
  // state is 1 every time at this point
  // state outside closure is not affected
}
var interval = setInterval(what, 1000);

因此,实际上该函数是在没有任何参数的情况下传递到setInterval()的。你放入function what(){}的任何参数都必须由setInterval()传递一个参数,而则不传递这样的参数。

看看这个:

function whatever(func){
  // takes function argument like `setInterval()`
  // need to pass it something to have func take an argument
  func("We'll just pass our function this String");
}
whatever(console.log); // now console.log() is passed an argument

因此,您可以看到,将函数作为参数的函数决定了作为参数传递的函数传递哪些参数。

我是否通过引用将状态传递到匿名函数中?

是的。尽管没有"关闭"setInterval非常复杂,因为它实际上不允许你传递任何东西。

JavaScript 不支持通过引用传递

是的。我们不会使用对变量的引用,而是使用一个对象来存储状态。您将修改传递的对象,而不是修改闭包变量。

var state = {
    value: 0
};
state.interval = setInterval(function() { 
    // Do something depending on this.value
}.bind(state), 1000);