我想提高对可重入这个词的理解。
这个函数是可重入的吗?
function* foo() {
yield 1;
yield 2;
}
还有这个?
function foo() {
return 1;
}
还有这个?
var x = 0;
function foo() {
return x++;
}
还有这个?
function foo() {
setTimeout(foo, 1000);
}
可重入函数是可以恢复执行的函数:
在计算中,如果计算机程序或子例程可以在执行过程中被中断,然后在其先前的调用完成执行之前再次安全地调用(“重新进入”),则该计算机程序或子例程被称为可重入。
在浏览器/节点 JavaScript 中,所有多处理都是协作的(没有中断或上下文切换)。 JavaScript 中的常规函数始终运行完成。 (1)
因此,在您的情况下 - 唯一的可重入函数是第一个函数,因为它不会运行其代码直至完成,并且可以在稍后恢复。
确实 - 可以说生成器使用可重入语法在 JavaScript 中实现协作式多任务处理。在生成器之前,所有代码都运行完成。
(1) 或者说它永远不会停止,但它永远不会被打断。另外 - 在公共平台上。有些平台(如 Rhino)违反了规则。它们非常罕见,并且不使用与浏览器/节点 JS 相同的并发执行模型。
JavaScript 没有可重入的概念,因为对于可重入,您需要第二个线程来调用正在暂停的同一函数。
即使使用示例(1)中的
yield
,该函数也会被暂停并在下一次迭代中恢复,但是您不能让另一个线程在暂停时再次调用同一函数,因为没有其他线程。如果您在单个线程中执行此操作(如下面的代码所示)并再次调用生成器函数,它会返回一个新的不同函数。这就是为什么它被称为生成器函数。所以你不要叫同一个。
function* foo(index) {
while (index < 2) {
yield index;
index++;
}
}
const iterator = foo(0);
console.log(iterator.next().value);
// Expected output: 0
const iterator2 = foo(0);
if (iterator === iterator2) console.log('same');
else console.log('not same function');
console.log(iterator.next().value);
// Expected output: 1
console.log(iterator2.next().value);
// Expected output: 0
输出:
> 0
> "not same function"
> 1
> 0
总而言之,要谈论可重入,您需要多线程。如果没有多线程,答案纯粹是理论上的。有人可能会说所有 JavaScript 函数都是可重入的,因为它们不容易受到重入问题的影响。另一位可能会说它们不是,因为它们不能被打断。
即使有
yield
,功能也会被中断吗?并非如此,它只是返回一个新生成的函数,该函数将运行完成以覆盖一次迭代。
这只是一个理论上的讨论,因为即使我们弄错了,也不会发生什么不好的事情,因为我们没有第二个线程来第二次同时调用它!