当前位置:  开发笔记 > 编程语言 > 正文

什么是词汇范围?

如何解决《什么是词汇范围?》经验,为你挑选了8个好方法。

有人可以给我一个关于词汇范围的简要介绍吗?



1> AraK..:

我通过例子理解它们.:)

首先,词典范围(也称为静态范围),采用类C语法:

void fun()
{
    int x = 5;

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

每个内在级别都可以访问其外层.

还有另一种方法,称为动态范围,首先实现Lisp,再次使用类似C语法的语法:

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();

调用链取决于运行时条件.如果是,则调用链如下所示:

dummy1 --> fun()

如果条件为假:

dummy2 --> fun()

fun两种情况的外部范围都是调用者加上调用者的调用者等等.

只是提到C语言不允许嵌套函数或动态作用域.


我还想指出一个我刚刚发现的非常容易理解的教程.Arak的例子很好,但对于需要更多示例的人来说可能太短了(实际上,与其他语言相比......).看一看.理解*this*很重要,因为该关键字将引导我们理解词汇范围.http://howtonode.org/what-is-this
这是一个很好的答案.但问题是用"JavaScript"标记.因此,我认为这不应该被标记为已接受的答案.JS中的词汇范围是不同的
非常好的答案.谢谢.@Boyang我不同意.我不是Lisp编码器,但发现Lisp示例很有用,因为它是动态范围的一个例子,你在JS中没有.
最初我认为这个例子是有效的C代码,并且对C中是否存在动态范围感到困惑.也许最后的免责声明可能会转移到代码示例之前?

2> Pierre Sprin..:

让我们尝试最短的定义:

词法范围定义如何在嵌套函数中解析变量名称:内部函数包含父函数的范围,即使父函数已返回.

这就是它的全部!


最后一部分:“即使父函数已返回”也被称为Closure。

3> kta..:
var scope = "I am global";
function whatismyscope(){
   var scope = "I am just a local";
   function func() {return scope;}
   return func;
}

whatismyscope()()

上面的代码将返回"我只是一个本地".它不会回归"我是一个全球化的".因为函数func()计算最初定义的位于函数whatismyscope范围内的位置.

它不会受到任何调用(全局范围/来自另一个函数)的困扰,这就是为什么全局范围值我是全局的不会被打印的原因.

这称为词法作用域,其中" 函数使用在定义时生效的作用域链来执行 " - 根据JavaScript定义指南.

词汇范围是一个非常强大的概念.

希望这可以帮助..:)



4> Ralph M. Ric..:

范围定义了可用的功能,变量等区域.例如,变量的可用性在其上下文中定义,比如函数,文件或对象,它们是在中定义的.我们通常称这些局部变量.

词汇部分意味着您可以从阅读源代码中派生范围.

词法范围也称为静态范围.

动态范围定义了可在定义后从任何位置调用或引用的全局变量.有时它们被称为全局变量,即使大多数programmin语言中的全局变量都是词法范围.这意味着,它可以从读取变量在此上下文中可用的代码中派生而来.也许必须遵循uses或includes子句来查找instatiation或定义,但代码/编译器知道这个地方的变量.

相比之下,在动态范围中,首先在本地函数中搜索,然后在调用本地函数的函数中搜索,然后在调用该函数的函数中搜索,依此类推,调用堆栈."动态"指的是变化,因为每次调用给定函数时调用堆栈都可以不同,因此函数可能会根据调用它的位置命中不同的变量.(见这里)

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

有关详细信息,请参阅此处和此处.

Delphi/Object Pascal中的一些示例

德尔福有词汇范围.

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')的代码将得到结果与否.对RegisterClass()的调用不必使用GetClass();在单元的词法范围内;

动态范围的另一种可能性是Delphi 2009 中的匿名方法(闭包),因为它们知道其调用函数的变量.它不会递归地跟随调用路径,因此不是完全动态的.


实际上私人可以在定义类的整个单元中访问.这就是D2006中引入"严格私密"的原因.
普通语言的+1(与复杂的语言和没有太多描述的例子相对)

5> Evan Meagher..:

词法(AKA静态)范围是指仅根据其在文本语料库中的位置来确定变量的范围.变量始终指向其顶级环境.与动态范围相关的理解很好.



6> SimplGy..:

我喜欢@Arak等人的全功能,语言无关的答案.既然这个问题被标记为JavaScript,我想填写一些非常特定于这种语言的注释.

在javascript中,我们对范围界定的选择是:

原样(没有范围调整)

词法 var _this = this; function callback(){ console.log(_this); }

callback.bind(this)

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

以下是展示这两种方法的示例.每次做出关于如何调整回调范围的决定时都会这样做,因此这适用于promises,事件处理程序等.

词汇

以下是Lexical ScopingJavaScript中可能的回调术语:

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`
  }
//...

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



7> 小智..:

词法作用域:在函数外部声明的变量是全局变量,在JavaScript程序中随处可见.在函数内声明的变量具有函数范围,并且仅对出现在该函数内的代码可见.



8> Robert Rocha..:

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();

推荐阅读
mobiledu2402851173
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有