javascript - Javascript 中的声明式环境记录和范围

标签 javascript scope

我目前正在学习 Javascript 范围,并尝试为正在发生的事情制定一些规则。 但每次意想不到的行为都会打破它们。所以我需要帮助。

考虑下面的例子

console.log("v" in this);    //true
console.log(v)     //undefined
{
    {
        function a() {
            1;
        }
    }
    {
        function a() {
            2;
        }
        {
            function v() {
                3;
            }
        }
    }
}
console.log(a);    //ƒ a() {2}

函数 v 在内存中,但我不能在第 2 行使用它。但在这个例子中我可以。

console.log(v);
{
    function v() {
        1;
    }
}

我对编译器在执行脚本之前所做的规则以及评估声明的步骤(顺序)感到困惑,包括使用 let,const,varfunction 声明和 class 声明。 我读过关于作用域的博客和书籍,但几乎所有这些都将变量、函数和类视为独立的东西,而不是附加在作用域的 D.E.R 中的属性

最佳答案

function v is in memory but I can't use it at line 2. But in this example I can

不,两个示例的行为方式相同。在这两种情况下,v 都是在一个 block 内声明的,并且在这两种情况下,它的值都是 undefined 到你记录它的地方。

在松散模式(又名“草率”模式)下,符合特定条件的 block 中的函数声明会在函数(或全局)范围内创建提升绑定(bind)(v,在这种情况下) ,而不是 block 范围。该绑定(bind)使用值 undefined 进行初始化;直到在代码的逐步执行中到达声明,它才获得分配给它的功能。 还有一个隐藏函数/全局绑定(bind)的 block 局部绑定(bind),它在 block 的开头用函数初始化。是的,这非常令人困惑;这是因为这是将 ES2015 中的规则追溯应用到跨浏览器引擎的通用功能子集,这些浏览器引擎使用 block 声明的函数扩展了 JavaScript(这不在规范中,但是允许的扩展)。

但是,不要依赖它,甚至真的费心去记住它。这是遗留兼容性问题。

相反,使用严格模式,在该模式下,声明成为 block 的局部(在 block 内完全提升)并且您根本不能在 block 外使用 v :

"use strict";
console.log("v" in this);    // false
console.log(v)               // ReferenceError
{
    {
        function a() {
            1;
        }
    }
    {
        function a() {
            2;
        }
        {
            function v() {
                3;
            }
        }
    }
}
console.log(a);

关于javascript - Javascript 中的声明式环境记录和范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58823846/

相关文章:

Javascript 使用数组将 li 添加到 ul

ruby-on-rails - ActiveRecord 与范围的关系

html - 推荐使用哪个 JavaScript 库来实现整洁的 UI 效果?

javascript - 通过history.pushState改变内容

JavaScript 在文本框中自动添加 .00

javascript - 递归函数不返回所有数据

javascript - 混淆 JavaScript 作用域

javascript - 指向局部变量时未定义错误属性

c# - 如何通过属性使字典只读?

swift - 使用超出其范围的变量