【问题标题】:What is block inside [[scope]] key and when it is created?[[scope]] 键内的块是什么以及它是何时创建的?
【发布时间】:2021-09-13 07:30:21
【问题描述】:

我尝试了以下代码

let let_arr = [];
for (let i = 0; i < 4; i++) {
  let_arr[i] = () => {
    return {
        let_i: i
    }
  };
}
console.log(let_arr);

当我们在 for 循环中使用 let 时,我发现 block 键存在。

[ƒ, ƒ, ƒ, ƒ]
  0: () => {…}
    arguments: (...)
    caller: (...)
    length: 0
    name: ""__proto__: ƒ ()
    [[FunctionLocation]]: iif.js:26
    [[Scopes]]: Scopes[3]
        0: Block {i: 0}
        1: Script {let_arr: Array(4), var_arr: Array(4)}
        2: Global {window: Window, self: Window, document: document, name: "", location: Location, …}

当使用 var 时 for (var i = 0; i &lt; 4; i++) 块元素丢失。

[[Scopes]]: Scopes[2]
    0: Script {let_arr: Array(4), var_arr: Array(4)}
    1: Global {window: Window, self: Window, document: document, name: "", location: Location, …}

【问题讨论】:

  • Global

标签: javascript function var let


【解决方案1】:

Javascript函数实际上是闭包,也就是说,当你将一个函数保存在某个地方时,不仅保留了它的代码,还保留了创建时所有可用的变量。变量存储在称为作用域的字典中,它们可以相互嵌套(“作用域链”)。

为了节省内存,引擎只保留函数中实际使用的范围。如果作用域不包含let/const,则将其视为未使用并省略。如果作用域确实包含let,但该变量未在函数中使用,则它也会被省略。否则,范围将保留并附加到闭包。

几个插图:

var f

{
    var a
    f = () => a   // Global
}
console.dir(f)

//

{
    let a
    f = () => a
}
console.dir(f) // Block a + Global

//

{
    let a
    {
        let b
        {
            let c
            f = () => b  
        }
    }
}
console.dir(f)  // Block b + Global

//


{
    let a
    {
        let b
        {
            let c
            f = () => eval("b")
        }
    }
}
console.dir(f) // 'eval' retains everything

【讨论】:

  • 从您的回答中学习时,我还发现了 Script {a:11}。代码是 var f;让 a = 11; f = () => a;控制台.dir(f); {让b; f = () => b; } 控制台.dir(f);块和脚本先生有什么不同?
  • @devumesh:几乎没有。 Script 是顶级Block
【解决方案2】:

这是预期的行为,因为如果您使用 var 声明变量,则块范围内没有变量。在这种情况下,它将被提升到全局范围。你可以阅读更多关于块范围here的信息。

【讨论】:

    猜你喜欢
    • 2015-01-27
    • 2021-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-07
    • 2020-08-06
    • 2011-12-27
    相关资源
    最近更新 更多