词汇范围的简要介绍是什么?


当前回答

作用域是可访问变量/绑定的上下文。词法范围是指封闭词法块的局部范围,而不是全局范围。

其他回答

让我们尝试最短的定义:

词法作用域定义了如何在嵌套函数中解析变量名:即使父函数已返回,内部函数也包含父函数的作用域。

这就是它的全部!

IBM将其定义为:

一个程序或段单元的一部分,其中有一个声明应用。例程中声明的标识符在例程和所有嵌套例程中。如果嵌套例程声明具有相同名称的项,外部项在嵌套例程。

示例1:

function x() {
    /*
    Variable 'a' is only available to function 'x' and function 'y'.
    In other words the area defined by 'x' is the lexical scope of
    variable 'a'
    */
    var a = "I am a";

    function y() {
        console.log( a )
    }
    y();

}
// outputs 'I am a'
x();

示例2:

function x() {

    var a = "I am a";

    function y() {
         /*
         If a nested routine declares an item with the same name,
         the outer item is not available in the nested routine.
         */
        var a = 'I am inner a';
        console.log( a )
    }
    y();

}
// outputs 'I am inner a'
x();

词汇范围是指从执行堆栈中的当前位置可见的标识符(例如,变量、函数等)的词汇。

- global execution context
    - foo
    - bar
    - function1 execution context
        - foo2
        - bar2
        - function2 execution context
            - foo3
            - bar3

foo和bar总是在可用标识符的词典中,因为它们是全局的。

当执行function1时,它可以访问foo2、bar2、foo和bar的词典。

当执行function2时,它可以访问foo3、bar3、foo2、bar2、foo和bar的词典。

全局和/或外部函数无法访问内部函数标识符的原因是,该函数的执行尚未发生,因此,其标识符均未分配给内存。此外,一旦内部上下文执行,它就会从执行堆栈中删除,这意味着它的所有标识符都已被垃圾收集,不再可用。

最后,这就是为什么嵌套的执行上下文总是可以访问它的祖先执行上下文,因此它可以访问更大的标识符词典。

See:

https://tylermcginnis.com/ultimate-guide-to-execution-contexts-hoisting-scopes-and-closures-in-javascript/https://developer.mozilla.org/en-US/docs/Glossary/Identifier

特别感谢@robr3rd帮助简化上述定义。

这是一个古老的问题,但这是我对它的看法。

词法(静态)范围是指源代码中变量的范围。

在JavaScript这样的语言中,函数可以被传递、附加和重新附加到其他对象,您可能会想到,这个范围将取决于当时调用该函数的人,但事实并非如此。以这种方式更改作用域将是动态作用域,而JavaScript不会这样做,除非可能使用此对象引用。

要说明这一点:

var a=“苹果”;函数doit(){var a=“ardvark”;返回函数(){警报(a);}}var test=doit();测试();

在示例中,变量a是全局定义的,但在doit()函数中隐藏。此函数返回另一个函数,如您所见,该函数依赖于自身范围之外的变量。

如果您运行这个,您会发现使用的值是aardwark,而不是apple,虽然它在test()函数的范围内,但不在原始函数的词法范围内。也就是说,使用的范围是源代码中显示的范围,而不是实际使用函数的范围。

这一事实可能会产生令人讨厌的后果。例如,您可能会决定更容易单独组织函数,然后在时间到来时使用它们,例如在事件处理程序中:

var a=“苹果”,b=“香蕉”;函数init(){var a=“ardvark”,b=“andicoot”;document.querySelector('button#a').onclick=函数(事件){警报(a);}document.querySelector('button#b').onclick=doB;}函数doB(事件){警报(b);}init();<button id=“a”>a</button><button id=“b”>b</button>

此代码示例分别执行其中一项。您可以看到,由于词法作用域,按钮A使用内部变量,而按钮B不使用。您可能最终嵌套的函数比您想要的更多。

顺便说一句,在这两个示例中,您还将注意到,即使包含函数函数已经运行,内部词汇范围内的变量仍然存在。这称为闭包,指的是嵌套函数对外部变量的访问,即使外部函数已经完成。JavaScript需要足够聪明,以确定这些变量是否不再需要,如果不需要,可以垃圾收集它们。

作用域是可访问变量/绑定的上下文。词法范围是指封闭词法块的局部范围,而不是全局范围。