gpt4 book ai didi

javascript - LexicalEnviroment 对象和 [[Environment]] 之间的关系

转载 作者:行者123 更新时间:2023-12-03 07:03:07 25 4
gpt4 key购买 nike

据说每个代码块都有一个名为 LexicalEnviroment 的隐藏对象。 .该对象包含对外部作用域的引用和 EnviromentRecord ,其中包含有关当前作用域的信息。
另一方面,据说函数能够闭包,这要归功于 [[Enviroment]]构造“记住函数的定义位置”。
搞糊涂了,LexicalEnviroment有什么关系对象和 [[Enviroment]] ?
他们是一回事吗?只有函数有[[Enviroment]]构造?他们有 LexicalEnviroment对象呢?

最佳答案

tl;博士
它们都是 Environment Record 的实例.LexicalEnvironment只是执行上下文的一个组件(函数不能有 LexicalEnvironment ),并且在调用函数时,一个新的 LexicalEnvironment为当前上下文创建,其 [[OuterEnv]]字段被设置为函数 [[Environment]] field 。
如果是 Javascript,我想应该是:

function handleInvokeFunction(func) {
const localEnv = new EnvironmentRecord();
localEnv.set('[[OuterEnv]]', func['[[Environment]]'])
calleeContext.lexicalEnvironment = localEnv;
}

免责声明:我不是该主题的专家。我只是想给你一个整体的想法,同时等待真正的专家在这里插话。
环境记录
Environment Records ,为了记录(双关语),保存要执行的功能所需的所有信息。例如,对于函数,它们保存变量声明,而 this值(value)。当然,这过于简单化 [src] .

Environment Record is a specification type used to define the association of Identifiers to specific variables and functions.


Each time such code is evaluated, a new Environment Record is created to record the identifier bindings that are created by that code.


关于环境记录的一件有趣的事情是,它们负责允许访问父变量,例如:
// Environment Record "EnvA"
const hello = "world";
if (1) {
// Environment Record "EnvB"
console.log(hello);
}

// outputs: world
那是因为他们有一个名为 [[OuterEnv]] 的字段。 ,它指向父环境。所以在上面的例子中, [[OuterEnv]] “EnvB”字段设置为“EnvA” [src] .

Every Environment Record has an [[OuterEnv]] field, which is either null or a reference to an outer Environment Record.


每次运行时遇到新的代码块时,它都会执行以下步骤 [src] :
  • 创建一个新的环境记录。
  • 设置 [[OuterEnv]]新环境到旧(当前事件)环境的领域。
  • 返回新环境

  • 执行上下文
    为了对所有块执行此操作, 执行上下文堆栈 使用,这几乎就像一个 堆栈跟踪 [src] .不同之处在于,它不仅仅是在进入和退出 时推送和弹出。功能 (就像堆栈跟踪一样),它只会在进入或退出 时更改最上面的条目。代码块 (就像一个 if 块)。

    An execution context is a specification device that is used to track the runtime evaluation of code by an ECMAScript implementation.


    The execution context stack is used to track execution contexts.


    执行上下文有一个 LexicalEnvironment成分。需要跟踪该特定代码块中的变量。

    LexicalEnvironment: Identifies the Environment Record used to resolve identifier references made by code within this execution context. [src]

    LexicalEnvironment 一个环境记录,所以它有一个 [[OuterEnv]]字段,这是运行时将相应更改的内容。 LexicalEnvironment不属于函数对象。它只属于一个执行上下文。
    正在运行 执行上下文表示当时运行时当前正在执行的代码块 [src] .

    The running execution context is always the top element of this stack.


    扩展上述步骤,当输入新的代码块时,实际会发生这种情况 [src] :
  • 使用正确的 [[OuterEnv]] 创建一个新的环境记录值(与以前相同的步骤)。
  • 使用新的环境记录作为运行记录。
  • 评估块内的所有行。
  • 恢复到以前的环境记录。
  • 返回结果并退出块。

  • 评论前面的例子,这就是会发生的事情:
    // This is Environment Record "EnvA".
    // The [[OuterEnv]] field for "EnvA" is null.
    // The running context LexicalEnvironment is "EnvA".

    const hello = "world";

    if (1) {

    // Found new block

    // Create a new Environment Record "EnvB".

    // Set the "EnvB" [[OuterEnv]] field to
    // the running context LexicalEnvironment.
    // In this case, its "EnvA".

    // Change the running context LexicalEnvironment to "EnvB".

    // Evaluate all lines in the body using the new
    // running context LexicalEnvironment.
    // In this case, its "EnvB".

    console.log(hello);

    // Restore the previous running context LexicalEnvironment.

    // Return the result.
    }

    // The running context LexicalEnvironment is Environment Record "A".
    // Since the inner block restored before returning, it didn't change.
    [[环境]]
    不过,还没有提到功能。这是不同的,因为函数可以在声明的范围之外执行。
    那就是 [[Environment]]出现。

    [[Environment]]: The Environment Record that the function was closed over. Used as the outer environment when evaluating the code of the function.


    当块内有函数时,运行 LexicalEnvironment存储为 [[Environment]]函数对象的字段 [step 35] [step 3] [step 14] .
    调用该函数时, [[Environment]]字段用作 [[OuterEnv]] [step 10] .
    这就像函数将所有它可以访问的变量存储在 [[Environment]] 中。 ,当被调用时,它可以使用 [[Environment]] 再次访问它们。 .
    与普通块的另一个区别是,在这种情况下,不是更改 正在运行 执行上下文,一个新的被创建并推送到堆栈 [creation in step 3] [push in step 12] [pop in step 8] .
    现在,尝试使用简单的代码:
    // This is Environment Record "EnvA".
    // The [[OuterEnv]] field for "EnvA" is null.
    // The running context LexicalEnvironment is "EnvA".

    const hello = "world";

    // Found a function, store the running context
    // into its [[Environment]] field, and do nothing else.

    function foo() {

    // This block runs only after invoking bar().

    // Create a new executing context "calleeContext".

    // Create a new Environment Record "EnvB".

    // Set the "EnvB" [[OuterEnv]] field, to the value
    // stored inside [[Environment]]. In this case, its "EnvA".

    // Set the LexicalEnvironment of "calleeContext" to "EnvB".

    // Push "calleeContext" to the execution context stack.
    // That makes "calleeContext" the running execution context.

    // Evaluate all lines in the body
    // using "calleeContext" LexicalEnvironment.
    // In this case, its "EnvB".

    // If a function is found here, set its
    // [[Environment]] to "calleeContext" LexicalEnvironment.

    console.log(hello); // works because `hello` was in "EnvA"

    // Pop "calleeContext" from the execution context stack.
    // "calleeContext" is no longer the running execution context.

    // Return the result.
    }

    const bar = foo;
    bar();

    // The [[Environment]] of `bar` is still "EnvA".
    // The running context LexicalEnvironment is still "EnvA".
    由于该示例在声明它的同一环境中调用该函数,因此它实际上并未使用“闭包”,但您可能已经明白了。
    综上所述
    虽然两者 [[Environment]]LexicalEnvironmentEnvironment Records ,它们用于不同的东西。 [[Environment]]持有 LexicalEnvironment函数被声明的地方。 LexicalEnvironment是执行上下文的一个组件,它存储有关该特定代码块中变量的信息。

    关于javascript - LexicalEnviroment 对象和 [[Environment]] 之间的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64202695/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com