首页 > 解决方案 > [[scope]] 键内的块是什么以及它是何时创建的?

问题描述

我尝试了以下代码

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 < 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, …}

标签: javascriptfunctionvarlet

解决方案


Javascript functions are actually closures, that is, when you save a function somewhere, not only its code is retained, but also all variables available at the creation time. Variables are stored in dictionaries called scopes, which can be nested in each other ("scope chain").

In order to conserve memory, the engine only retains scopes that are actually used in the function. If a scope does not contain let/const, it is considered unused and omitted. If a scope does contain let, but that variable is not used in the function, it's also omitted. Otherwise the scope is retained and attached to the closure.

A couple of illustrations:

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


推荐阅读