为什么 setTimeout 使用我的函数的旧版本?
Why does setTimeout use the old version of my function?
当我运行以下代码时:
let fn = () => console.log('original fn was called');
fn();
setTimeout(fn.bind(this), 250);
setTimeout(() => fn(), 500);
setTimeout(fn, 750);
fn = () => console.log('updated fn was called');
这样输出:
original fn was called
original fn was called
updated fn was called
original fn was called
我直觉地理解为什么输出前两行:
- 函数被立即调用。
bind
方法正在从 fn
生成一个新函数,因此 'locking' 在它的行为中。
但是,我对为什么第 3 行和第 4 行不同感到困惑。我想在第三种情况下,在调用包装匿名函数之前不会评估对 fn
的引用。因此,它将利用 fn
的更新实现是有道理的。但是在第4种情况下,setTimeout为什么不使用最新版本的fn
?
仅当解释器 运行 执行语句时才评估变量引用。在 1、2 和 4 中,您立即引用 fn
,并以某种方式使用它传递给 setTimeout
:
fn();
setTimeout(fn.bind(this), 250);
setTimeout(fn, 750);
在 3 中,您没有立即引用 fn
- 您正在传递一个不同的匿名函数。只有当那个匿名函数 运行s 和它里面的行得到 运行 时,解释器才会检查这些行上的引用以查看变量名称指向什么值。
But in the 4th case, why doesn't setTimeout make use of the latest version of fn?
因为你在调用setTimeout
时直接引用了fn
,就像情况1和2一样
在第 3 种情况下,您有一个 包含 对 fn
的引用的函数,它将在匿名函数 运行 和口译员遇到了那条线——但之前没有。
“fn”只是对一个对象的引用:首先是“原始”函数;最后是“更新”功能。在第三种情况下,setTimeout 调用 ()=>fn,此时 fn 具有“更新”值,但在第四种情况下,“原始”对象被传递给 setTimeout...
摘要如下:
let fn = () => console.log('original fn was called');
fn = () => console.log('updated fn was called');
执行上述操作时,您在内存中创建了两个不同的函数。但是 - 通过第二个语句,您丢失了指向第一个函数的任何引用。
然后,
setTimeout(() => fn(), 500);
.. 你说 fn
引用的任何内容都在 500 毫秒后执行。此时引用指向代码中的“更新”函数。
setTimeout(fn, 750);
上面你把第一个函数的引用给了setTimeout。它存储此引用并在 750ms
后执行
当我运行以下代码时:
let fn = () => console.log('original fn was called');
fn();
setTimeout(fn.bind(this), 250);
setTimeout(() => fn(), 500);
setTimeout(fn, 750);
fn = () => console.log('updated fn was called');
这样输出:
original fn was called
original fn was called
updated fn was called
original fn was called
我直觉地理解为什么输出前两行:
- 函数被立即调用。
bind
方法正在从fn
生成一个新函数,因此 'locking' 在它的行为中。
但是,我对为什么第 3 行和第 4 行不同感到困惑。我想在第三种情况下,在调用包装匿名函数之前不会评估对 fn
的引用。因此,它将利用 fn
的更新实现是有道理的。但是在第4种情况下,setTimeout为什么不使用最新版本的fn
?
仅当解释器 运行 执行语句时才评估变量引用。在 1、2 和 4 中,您立即引用 fn
,并以某种方式使用它传递给 setTimeout
:
fn();
setTimeout(fn.bind(this), 250);
setTimeout(fn, 750);
在 3 中,您没有立即引用 fn
- 您正在传递一个不同的匿名函数。只有当那个匿名函数 运行s 和它里面的行得到 运行 时,解释器才会检查这些行上的引用以查看变量名称指向什么值。
But in the 4th case, why doesn't setTimeout make use of the latest version of fn?
因为你在调用setTimeout
时直接引用了fn
,就像情况1和2一样
在第 3 种情况下,您有一个 包含 对 fn
的引用的函数,它将在匿名函数 运行 和口译员遇到了那条线——但之前没有。
“fn”只是对一个对象的引用:首先是“原始”函数;最后是“更新”功能。在第三种情况下,setTimeout 调用 ()=>fn,此时 fn 具有“更新”值,但在第四种情况下,“原始”对象被传递给 setTimeout...
摘要如下:
let fn = () => console.log('original fn was called');
fn = () => console.log('updated fn was called');
执行上述操作时,您在内存中创建了两个不同的函数。但是 - 通过第二个语句,您丢失了指向第一个函数的任何引用。
然后,
setTimeout(() => fn(), 500);
.. 你说 fn
引用的任何内容都在 500 毫秒后执行。此时引用指向代码中的“更新”函数。
setTimeout(fn, 750);
上面你把第一个函数的引用给了setTimeout。它存储此引用并在 750ms
后执行