JavaScript:理解闭包和提升

科德史密斯

我知道函数声明被提升到其作用域的顶部。这允许我们在 JavaScript 中实际声明之前使用这些函数:

sayHello(); // It works!

function sayHello() {
  console.log('Hello');
}

我也明白闭包使函数能够保留对在同一范围内声明的变量的引用:

function outerFxn() {
  let num = 0;

  function innerFxn() {
    console.log(num);
    num++;
  }

  return innerFxn;
}

const logNum = outerFxn();
logNum(); // 0
logNum(); // 1
logNum(); // 2

到现在为止还挺好。但是这里有一些奇怪的地方,我希望有人能确切地解释发生了什么......

场景一:可以理解的闭包

function zero(cb) {
  return setTimeout(cb, 0);
}

function test1() {
  let txt = 'this is a test message';

  function log() {
    console.log(txt);
  }

  zero(log);
}

在上面的示例中,该log函数保留对创建它的作用域的引用,并保留txt变量。然后,当稍后在 中执行时setTimeout,它成功地记录了txt变量的值。伟大的。然后就是这个...

场景2:发生了什么?

function zero(cb) {
  return setTimeout(cb, 0);
}

function test1() {
  function log() {
    console.log(txt);
  }

  let txt = 'this is a test message';

  zero(log);
}

我已经将log函数声明移到了作用域的顶部(无论如何它都会被提升到那里,对吗?),然后我声明了txt它下面变量。这一切仍然有效,我不知道为什么。's 和's 没有被提升时,如何log保留对txt变量的引用是否对闭包范围进行了整体分析我可以在这里一步一步地对 JavaScript 引擎正在做的事情进行一些清晰的说明。谢谢你的土地!letconst

乔治

“是否对闭包范围进行了整体分析?” - 是的。闭包保留范围在你(词汇上)离开它的那一刻。在您的示例中,txt当您到达}in时确实存在test1,因此它在范围内,并且log访问它没有问题。

注意上面的“词法”:绑定是在运行之前完成的,只有你的块结构才是重要的。所以即使这样也可以,尽管从“动态”的角度来看它不应该:

function test1() {
    function log() {
        console.log(txt);
    }

    zero(log);
    let txt = 'this is a test message';
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章