什么是词汇范围?

有人能够给我简要介绍词汇做用域吗? javascript


#1楼

词法(AKA静态)做用域是指仅根据变量在代码文本语料库中的位置来肯定变量的范围。 变量始终引用其顶层环境。 最好将其与动态范围相关联。 html


#2楼

范围定义了功能,变量等可用的区域。 例如,变量的可用性是在其上下文中定义的,也就是说,它们是在函数,文件或对象中定义的。咱们一般将这些变量称为局部变量。 java

词法部分意味着您能够经过阅读源代码来得出范围。 git

词法范围也称为静态范围。 github

动态范围定义了能够在定义后从任何地方调用或引用的全局变量。 有时它们被称为全局变量,即便大多数programmin语言中的全局变量具备词法范围。 这意味着,能够从读取代码中得出该变量在此上下文中可用的信息。 也许必须遵循use或include子句才能找到实例或定义,可是代码/编译器知道该位置的变量。 闭包

相比之下,在动态做用域中,您首先搜索本地函数,而后搜索调用本地函数的函数,而后搜索调用该函数的函数,依此类推,直到调用堆栈。 “动态”是指更改,由于每次调用给定函数时,调用堆栈均可能不一样,所以该函数可能会根据调用源的不一样而使用不一样的变量。 (请参阅此处app

要查看动态范围的有趣示例,请参见此处函数

有关更多详细信息,请参见此处此处this

Delphi / Object Pascal中的一些示例 spa

Delphi具备词法范围。

unit Main;
uses aUnit;  // makes available all variables in interface section of aUnit

interface

  var aGlobal: string; // global in the scope of all units that use Main;
  type 
    TmyClass = class
      strict private aPrivateVar: Integer; // only known by objects of this class type
                                    // lexical: within class definition, 
                                    // reserved word private   
      public aPublicVar: double;    // known to everyboday that has access to a 
                                    // object of this class type
    end;

implementation

  var aLocalGlobal: string; // known to all functions following 
                            // the definition in this unit    

end.

最接近动态范围的Delphi是RegisterClass()/ GetClass()函数对。 有关其用途,请参见此处

假设经过注册代码没法预测调用RegisterClass([TmyClass])的时间(经过用户调用按钮的点击方法调用),调用GetClass('TmyClass')的代码将得到结果与否。 使用GetClass()调用RegisterClass()没必要在单元的词汇范围内;

动态范围的另外一种可能性是Delphi 2009中的匿名方法 (闭包),由于它们知道其调用函数的变量。 它不会从那里递归地遵循调用路径,所以不是彻底动态的。


#3楼

我经过示例了解它们。 :)

首先,采用相似C的语法的词法做用域(也称为静态做用域):

void fun()
{
    int x = 5;

    void fun2()
    {
        printf("%d", x);
    }
}

每一个内部级别均可以访问其外部级别。

一样,在相似C的语法中,Lisp的第一个实现使用了另外一种称为动态范围的方法:

void fun()
{
    printf("%d", x);
}

void dummy1()
{
    int x = 5;

    fun();
}

void dummy2()
{
    int x = 10;

    fun();
}

这里fun既能够访问xdummy1dummy2 ,或x任何函数调用funx在其声明。

dummy1();

将打印5

dummy2();

将打印10。

第一个称为静态,由于它能够在编译时推导,第二个称为动态,由于外部范围是动态的,而且取决于函数的链调用。

我发现静态范围界定对眼睛来讲更容易。 最终,大多数语言甚至都使用Lisp(能够同时作,对吗?)。 动态做用域就像将全部变量的引用传递给调用的函数同样。

为何编译器没法推断函数的外部动态范围的示例,请考虑咱们的最后一个示例,若是咱们编写以下代码:

if(/* some condition */)
    dummy1();
else
    dummy2();

调用链取决于运行时条件。 若是为true,则调用链以下所示:

dummy1 --> fun()

若是条件为假:

dummy2 --> fun()

在这两种状况下, fun的外部范围是调用者加上调用者的调用者,依此类推

仅说起C语言既不容许嵌套函数也不容许动态做用域。


#4楼

var scope = "I am global";
function whatismyscope(){
   var scope = "I am just a local";
   function func() {return scope;}
   return func;
}

whatismyscope()()

上面的代码将返回“我只是本地人”。 它不会返回“我是全球”。 由于函数func()会在函数whatismyscope的范围内计算最初定义的位置。

它不会被调用的内容所困扰(即便是全局做用域,甚至也不会从另外一个函数中),这就是为何不会打印我是全局的全局做用域值的缘由。

这称为词法做用域,其中“根据JavaScript定义指南,使用定义时有效的做用域链执行函数 ”。

词法范围是一个很是很是强大的概念。

但愿这能够帮助..:)


#5楼

我喜欢@Arak之类的功能全面,与语言无关的答案。 因为此问题被标记为JavaScript ,所以,我想介绍一些针对该语言的注释。

在javascript中,做用域的选择是:

  • 原样(不调整范围)
  • 词法var _this = this; function callback(){ console.log(_this); } var _this = this; function callback(){ console.log(_this); }
  • 绑定callback.bind(this)

我认为,值得注意的是JavaScript 并无真正的动态做用域.bind调整this关键字,这很接近,但在技术上并不相同。

这是演示两种方法的示例。 每次决定如何肯定回调范围时,您都须要执行此操做,所以这适用于Promise,事件处理程序等。

词法

您可能会在这里用JavaScript称呼回调的Lexical Scoping

var downloadManager = {
  initialize: function() {
    var _this = this; // Set up `_this` for lexical access
    $('.downloadLink').on('click', function () {
      _this.startDownload();
    });
  },
  startDownload: function(){
    this.thinking = true;
    // request the file from the server and bind more callbacks for when it returns success or failure
  }
  //...
};

范围的另外一种方法是使用Function.prototype.bind

var downloadManager = {
  initialize: function() {
    $('.downloadLink').on('click', function () {
      this.startDownload();
    }.bind(this)); // create a function object bound to `this`
  }
//...

据我所知,这些方法在行为上是等效的。

相关文章
相关标签/搜索