JavaScript中的词法范围

时间:2018-01-17 06:56:42

标签: javascript scope global lexical

我对JavaScript的确切范围如何工作有点困惑,主要是词法范围。我知道全局范围内的变量可以在任何地方访问,而在JavaScript中创建新范围的唯一方法是通过创建函数(或在ES6中使用let)。但是,我真的不明白词汇范围/意味着什么。我已经浏览了整个互联网,无法找到明确的解释。

我觉得我有点开始理解它,但是让我向你确认JavaScript向导,以确保我是正确的。

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

var x = "global";

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

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

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


bar();
baz();

打印到控制台的内容是"全球"两次。这是因为当调用函数foo时,解释器首先检查foo的范围,看它是否有变量" x"然后检查全局范围,而不是bar或baz范围。变量" x"被抓住,而不是从调用函数foo的位置,而是从它创建的位置,因此在词法范围内。我是否正确,这是否有意义?

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

最后,我的最后一个例子是箭头功能。它们允许词汇范围界定"这个",对吗?所以,例如,

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

而不是"这个"如果它是一个标准的内联函数,则被绑定到全局对象,"这个"由于"这个"的词汇范围,因此必然会成为obj。带箭头功能。

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

感谢。

4 个答案:

答案 0 :(得分:1)

您对范围如何适用于标准函数(包括闭包内的闭包)的理解是正确的,但对于箭头函数,这种说法是错误的:

  

“this”与obj绑定,因为带有箭头函数的“this”的词汇范围。

使用函数内的箭头函数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 } );

答案 1 :(得分:1)

要了解词汇范围,您需要对范围有一个基本的了解。在javascript中,我们将范围分为三种类型

  1. 功能范围
  2. 块范围
  3. 词汇范围

功能范围->在功能范围内定义的变量在功能范围内考虑。 var 关键字用于在功能范围内定义变量。

阻止范围->在if,switch condition,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未定义

词法作用域->在第一行中,我想说“子作用域可以访问父作用域中的变量” `

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从最内层的范围开始并向外搜索,直到找到所要查找的变量。 词法作用域很好,因为我们可以通过查看代码轻松地弄清楚变量的值;而在动态范围界定中,变量的含义可以在运行时通过增加难度来改变

答案 2 :(得分:0)

当您查看某个程序的某些源代码时,您正在查看其词法结构。当程序实际运行时,执行可以跳转并且事物的评估可以改变。这是所有开始有意义的部分。

您可能希望将其视为功能词汇范围阻止词汇范围。对于其他人,你似乎已经掌握了它的想法。

答案 3 :(得分:-1)

&#34;全球&#34;打印两次是因为&#34; foo&#34;是关闭,已添加&#34; x&#34;全局范围的记忆,这就是我学习的方式,闭包是记住的功能