JavaScript 中的词法作用域

Lexical Scope in JavaScript

我对作用域在 JavaScript 中的确切工作方式感到有些困惑,主要是词法作用域。我知道全局范围内的变量在任何地方都可以访问,在 JavaScript 中创建新范围的唯一方法是通过创建函数(或在 ES6 中使用 let )。但是,我不太明白什么是词法作用域is/means。我在整个互联网上都看过,找不到明确的解释。

我觉得我有点开始理解它了,但让我向您确认一下 JavaScript 那里的向导以确保我是正确的。

因此,根据我的理解,词法作用域意味着静态作用域,例如,函数的作用域不是由调用它的位置创建的,而是由创建函数本身的位置创建的。下面的代码演示了这个概念:

var x = "global";

function foo() {
   console.log(x);
}

function bar() {
   var x = "bar";
   foo();
}

function baz() {
   var x = "baz";
   foo();
}


bar();
baz();

打印到控制台的是"global"两次。这是因为当函数 foo 被调用时,解释器首先检查 foo 的范围以查看它是否有变量 "x" 然后检查全局范围,而不是 bar 或 baz 范围。变量 "x" 不是从调用函数 foo 的地方获取的,而是从它创建的地方获取的,因此是词法范围的。我是对的,这有意义吗?

词法作用域的另一个例子是闭包,对吧?因此,例如,内部函数可以访问外部函数的变量,无论内部函数在哪里被调用,因为词法范围,对吗?

最后,我的最后一个例子是箭头函数。它们允许 "this" 的词法范围,对吗?所以,例如,

   var obj = {
       name: "Rob",
       print() {
       setTimeout(() => {
         console.log(this.name)
       }, 1000);
     }
   };

如果它是一个标准的内联函数,"this" 不会绑定到全局对象,"this" 会绑定到 obj,因为 "this" 的词法作用域带有箭头函数。

我说的都对吗?另外,有人能给我一个词法范围的明确定义吗? JavaScript 中还有其他我应该知道的词法范围示例吗?

谢谢。

当您查看程序的某些源代码时,您正在查看其词法结构。当程序实际运行时,执行可以跳来跳去,对事物的评估可以 change.This 是所有开始有意义的部分。

您可能希望将其视为功能词法作用域块词法作用域。至于其他的,你似乎已经掌握了它的想法。

"global" 被打印了两次,因为 "foo" 是一个 闭包 ,它已将 "x" 的全局范围添加到其内存中,这就是我的学习方式是,闭包是记住

的函数

你对标准函数(包括闭包内的闭包)作用域的理解是正确的,但对于箭头函数,这个说法是错误的:

"this" is bound to obj because of the lexical scoping of "this" with arrow functions.

函数内的箭头函数 this 与创建时函数外的任何 this 相同。在您的示例中,它未绑定到 obj,而是绑定到已绑定到正在创建 obj 的位置。

它在以下情况下很有用:

this.values.filter( x => x < this.max );

箭头函数内部 this 与函数外部相同。对于常规函数,它可能是这样写的:

this.values.filter( function ( x ) { return x < this.max }.bind( this ) );

或:

var self = this;
this.values.filter( function ( x ) { return x < self.max } );

要了解词法作用域,您需要对作用域有一个基本的了解。在javascript中,我们将作用域分为三种

  1. 函数范围
  2. 块范围
  3. 词法作用域

Function Scope -> 函数内部定义的变量在函数中被考虑 scope.the var 关键字用于定义函数范围内的变量。

块范围 -> 在 if、switch 条件、for 和 while 循环中的区域中定义的变量。 每当您看到“{}”花括号时,它就是一个块。在 Es6 中,const 和 let 关键字允许开发人员在块范围内声明变量。这意味着这些变量仅存在于相应的块中。

   function animal(){
    if(true){
        var animal1 = "cat";
        const animal2 = "dog";
        let animal3 = "rat";
    }
    console.log(animal1);
    console,log(animal2); //animal2 is not defiend
    console,log(animal3); //animal3 is not defiend
}
animal();

结果

未定义 animal2

未定义 animal3

词法作用域-> 在第 1 行我想说 "children scope have access to the variable in parent scope" `

var outerFunction = function()
{
    if(true){
        var x = 5;
        const y = 10;
    }

    var innerFunction = function(){
        if(true){
            alert(x);
            //alert(y);   //y is not defiend on line 13

        }
    }
    innerFunction();
}
 outerFunction();
 //console.log(x); // x is not defiend on line 20

`。 变量的范围由它们在源代码中的位置定义。 为了解析变量 javascript 从最里面的作用域开始向外搜索,直到找到它要查找的变量。 词法范围很好,因为我们可以通过查看代码轻松地找出变量的值;而在动态作用域中,变量的含义可以在运行时通过使其变得更加困难来改变