什么是词法范围?
词法作用域的简要介绍是什么?
What is a brief introduction to lexical scoping?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
词法作用域的简要介绍是什么?
What is a brief introduction to lexical scoping?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(22)
我通过例子来理解它们。 :)
首先,词法作用域(也称为静态作用域),采用类似 C 的语法:
每个内部级别都可以访问其外部级别。
还有另一种方法,称为动态作用域,由 的第一个实现使用Lisp,同样采用类似 C 的语法:
这里
fun
可以访问dummy1
或dummy2
中的x
code> 或任何调用fun
并声明了x
的函数中的任何x
。将打印 5,
将打印 10。
第一个称为静态,因为它可以在编译时推导,第二个称为动态,因为外部作用域是动态的并且取决于函数的链调用。
我发现静态范围更容易观察。 大多数语言最终都会走这条路,甚至 Lisp(两者都可以,对吧?)。 动态作用域就像将所有变量的引用传递给被调用的函数。
作为编译器无法推断函数的外部动态范围的示例,请考虑我们的最后一个示例。 如果我们这样写:
调用链取决于运行时条件。 如果为 true,则调用链如下所示:
如果条件为 false:
两种情况下
fun
的外部作用域都是调用者加上调用者的调用者,依此类推。需要提一下的是,C 语言不允许嵌套函数,也不允许动态作用域。
I understand them through examples. :)
First, lexical scope (also called static scope), in C-like syntax:
Every inner level can access its outer levels.
There is another way, called dynamic scope used by the first implementation of Lisp, again in a C-like syntax:
Here
fun
can either accessx
indummy1
ordummy2
, or anyx
in any function that callfun
withx
declared in it.will print 5,
will print 10.
The first one is called static because it can be deduced at compile-time, and the second is called dynamic because the outer scope is dynamic and depends on the chain call of the functions.
I find static scoping easier for the eye. Most languages went this way eventually, even Lisp (can do both, right?). Dynamic scoping is like passing references of all variables to the called function.
As an example of why the compiler can not deduce the outer dynamic scope of a function, consider our last example. If we write something like this:
The call chain depends on a run time condition. If it is true, then the call chain looks like:
If the condition is false:
The outer scope of
fun
in both cases is the caller plus the caller of the caller and so on.Just to mention that the C language does not allow nested functions nor dynamic scoping.
让我们尝试尽可能短的定义:
词法作用域定义如何在嵌套函数中解析变量名称:即使父函数已返回,内部函数也包含父函数的作用域。
这就是全部内容了!
Lets try the shortest possible definition:
Lexical Scoping defines how variable names are resolved in nested functions: inner functions contain the scope of parent functions even if the parent function has returned.
That is all there is to it!
上面的代码将返回“I am just a local”。 它不会返回“我是全局的”。 因为函数 func() 计算的是最初定义的位置,该函数位于函数 Whatismyscope 的范围内。
它不会受到任何调用的影响(全局作用域/甚至来自另一个函数内),这就是为什么全局作用域值 I am global 不会被打印。
这称为词法作用域,其中“函数使用定义时有效的作用域链执行” - 根据 JavaScript 定义指南。
词法范围是一个非常非常强大的概念。
The above code will return "I am just a local". It will not return "I am a global". Because the function func() counts where is was originally defined which is under the scope of function whatismyscope.
It will not bother from whatever it is being called(the global scope/from within another function even), that's why global scope value I am global will not be printed.
This is called lexical scoping where "functions are executed using the scope chain that was in effect when they were defined" - according to JavaScript Definition Guide.
Lexical scope is a very very powerful concept.
词法(又称为静态)作用域是指仅根据变量在代码文本语料库中的位置来确定变量的作用域。 变量始终引用其顶级环境。 最好从与动态作用域的关系来理解它。
Lexical (AKA static) scoping refers to determining a variable's scope based solely on its position within the textual corpus of code. A variable always refers to its top-level environment. It's good to understand it in relation to dynamic scope.
范围定义了函数、变量等可用的区域。 例如,变量的可用性是在其上下文中定义的,例如定义它们的函数、文件或对象。我们通常称这些变量为局部变量。
词法部分意味着您可以通过阅读源代码来推导出范围。
词法作用域也称为静态作用域。
动态作用域定义了全局变量,这些变量在定义后可以从任何地方调用或引用。 有时它们被称为全局变量,尽管大多数编程语言中的全局变量都具有词法范围。 这意味着,可以通过阅读代码得出该变量在此上下文中可用。 也许必须遵循使用或包含子句才能找到实例或定义,但代码/编译器知道这个地方的变量。
相比之下,在动态作用域中,您首先在本地函数中搜索,然后在调用本地函数的函数中搜索,然后在调用该函数的函数中搜索,依此类推,在调用堆栈中搜索。 “动态”指的是变化,因为每次调用给定函数时,调用堆栈都可能不同,因此该函数可能会根据调用位置而命中不同的变量。 (请参阅此处)
要查看动态作用域的有趣示例,请参阅此处。
有关更多详细信息,请参阅此处和此处。
Delphi/Object Pascal 中的一些示例
Delphi 具有词法作用域。
Delphi 最接近动态作用域的是 RegisterClass()/GetClass() 函数对。 有关其使用,请参阅
假设调用 RegisterClass([TmyClass]) 注册某个类的时间无法通过阅读代码来预测(它是在用户调用的按钮单击方法中调用的),调用 GetClass('TmyClass') 的代码将得到结果与否。 对 RegisterClass() 的调用不必在使用 GetClass() 的单元的词法范围内;
动态作用域的另一种可能性是匿名方法(闭包)在 Delphi 2009 中,因为他们知道调用函数的变量。 它不会递归地遵循从那里开始的调用路径,因此不是完全动态的。
Scope defines the area, where functions, variables and such are available. The availability of a variable for example is defined within its the context, let's say the function, file, or object, they are defined in. We usually call these local variables.
The lexical part means that you can derive the scope from reading the source code.
Lexical scope is also known as static scope.
Dynamic scope defines global variables that can be called or referenced from anywhere after being defined. Sometimes they are called global variables, even though global variables in most programmin languages are of lexical scope. This means, it can be derived from reading the code that the variable is available in this context. Maybe one has to follow a uses or includes clause to find the instatiation or definition, but the code/compiler knows about the variable in this place.
In dynamic scoping, by contrast, you search in the local function first, then you search in the function that called the local function, then you search in the function that called that function, and so on, up the call stack. "Dynamic" refers to change, in that the call stack can be different every time a given function is called, and so the function might hit different variables depending on where it is called from. (see here)
To see an interesting example for dynamic scope see here.
For further details see here and here.
Some examples in Delphi/Object Pascal
Delphi has lexical scope.
The closest Delphi gets to dynamic scope is the RegisterClass()/GetClass() function pair. For its use see here.
Let's say that the time RegisterClass([TmyClass]) is called to register a certain class cannot be predicted by reading the code (it gets called in a button click method called by the user), code calling GetClass('TmyClass') will get a result or not. The call to RegisterClass() does not have to be in the lexical scope of the unit using GetClass();
Another possibility for dynamic scope are anonymous methods (closures) in Delphi 2009, as they know the variables of their calling function. It does not follow the calling path from there recursively and therefore is not fully dynamic.
词法作用域意味着在嵌套的函数组中,内部函数可以访问其父作用域的变量和其他资源。
这意味着子函数在词法上绑定到其父函数的执行上下文。
词法作用域有时也称为静态作用域。
关于词法作用域,您会注意到它是向前工作的,这意味着该名称可以由其子级执行上下文访问。
但它不能向后工作到其父级,这意味着变量
likes
无法被其父级访问。这也告诉我们,在不同的执行中具有相同名称的变量上下文从执行堆栈的顶部到底部获得优先级。
最内层函数(执行堆栈的最顶层上下文)中名称与另一个变量相似的变量将具有更高的优先级。
来源。
Lexical scope means that in a nested group of functions, the inner functions have access to the variables and other resources of their parent scope.
This means that the child's functions are lexically bound to the execution context of their parents.
Lexical scope is sometimes also referred to as static scope.
The thing you will notice about lexical scope is that it works forward, meaning the name can be accessed by its children's execution contexts.
But it doesn't work backward to its parents, meaning that the variable
likes
cannot be accessed by its parents.This also tells us that variables having the same name in different execution contexts gain precedence from top to bottom of the execution stack.
A variable, having a name similar to another variable, in the innermost function (topmost context of the execution stack) will have higher precedence.
Source.
JavaScript 中的词法作用域意味着在函数外部定义的变量可以在变量声明后定义的另一个函数内部访问。 但反之则不然。 函数内部定义的变量将无法在该函数外部访问。
这个概念在 JavaScript 的闭包中大量使用。
假设我们有以下代码。
现在,当你调用 add() --> 这将打印 3。
因此,add() 函数正在访问在方法函数 add 之前定义的全局变量 x 。 这是由于 JavaScript 中的词法作用域而被调用的。
A lexical scope in JavaScript means that a variable defined outside a function can be accessible inside another function defined after the variable declaration. But the opposite is not true; the variables defined inside a function will not be accessible outside that function.
This concept is heavily used in closures in JavaScript.
Let's say we have the below code.
Now, when you call add() --> this will print 3.
So, the add() function is accessing the global variable
x
which is defined before method function add. This is called due to lexical scoping in JavaScript.我喜欢 @Arak 等人提供的功能齐全、与语言无关的答案。 由于这个问题被标记为JavaScript,所以我想添加一些针对该语言的注释。
在 JavaScript 中,我们对作用域的选择是:
var _this = this; 函数回调(){ console.log(_this); }
callback.bind(this)
我认为值得注意的是 JavaScript 实际上没有动态作用域。
.bind
调整this
关键字,这很接近,但技术上并不相同。这是演示这两种方法的示例。 每次决定如何确定回调的范围时,您都会执行此操作,因此这适用于 Promise、事件处理程序等。
词法
这就是 JavaScript 中回调的
词法作用域
:绑定
另一种限定作用域的方法是使用
Function.prototype.bind
:这些方法,只要我知道,行为上是等价的。
I love the fully featured, language-agnostic answers from folks like @Arak. Since this question was tagged JavaScript though, I'd like to chip in some notes very specific to this language.
In JavaScript our choices for scoping are:
var _this = this; function callback(){ console.log(_this); }
callback.bind(this)
It's worth noting, I think, that JavaScript doesn't really have dynamic scoping.
.bind
adjusts thethis
keyword, and that's close, but not technically the same.Here is an example demonstrating both approaches. You do this every time you make a decision about how to scope callbacks so this applies to promises, event handlers, and more.
Lexical
Here is what you might term
Lexical Scoping
of callbacks in JavaScript:Bound
Another way to scope is to use
Function.prototype.bind
:These methods are, as far as I know, behaviorally equivalent.
用简单的语言来说,词法作用域是在您的作用域之外定义的变量,或者上层作用域在您的作用域内自动可用,这意味着您不需要将其传递到那里。
示例:
// 输出:JavaScript
In simple language, lexical scope is a variable defined outside your scope or upper scope is automatically available inside your scope which means you don't need to pass it there.
Example:
// Output: JavaScript
词法作用域意味着函数在定义它的上下文中查找变量,而不是在它周围的作用域中查找变量。
如果您想了解更多详细信息,请查看 Lisp 中词法作用域的工作原理。 Kyle Cronin 在 Common Lisp 中的动态和词法变量<中选择的答案/a> 比这里的答案清楚得多。
巧合的是,我只在 Lisp 类中了解到这一点,而它恰好也适用于 JavaScript。
我在 Chrome 的控制台中运行了这段代码。
输出:
Lexical scope means that a function looks up variables in the context where it was defined, and not in the scope immediately around it.
Look at how lexical scope works in Lisp if you want more detail. The selected answer by Kyle Cronin in Dynamic and Lexical variables in Common Lisp is a lot clearer than the answers here.
Coincidentally I only learned about this in a Lisp class, and it happens to apply in JavaScript as well.
I ran this code in Chrome's console.
Output:
词法作用域:在函数外部声明的变量是全局变量,在 JavaScript 程序中随处可见。 函数内部声明的变量具有函数作用域,并且仅对该函数内部出现的代码可见。
Lexical scoping: Variables declared outside of a function are global variables and are visible everywhere in a JavaScript program. Variables declared inside a function have function scope and are visible only to code that appears inside that function.
IBM 将其定义为:
示例 1:
示例 2:
IBM defines it as:
Example 1:
Example 2:
我希望这对您有所帮助,这是我尝试稍微更抽象的定义:
词法范围:
某事物(例如函数或变量)对程序中其他元素的访问或范围由其在源代码中的位置决定。
Fwiw,我这里的逻辑只是建立在以下定义之上:
词汇:与语言的单词或词汇相关(特别是与语法或结构分开的单词){在我们的例子中 - 一种编程语言}。
范围(名词):操作范围{在我们的例子中范围是:可以访问的内容}。
请注意,1960 年定义
词法范围
来自 ALGOL 60 规范的内容比我上面的尝试要简洁得多:词法范围:应用名称与实体的绑定的源代码部分。 来源
I hope this is helpful, here is my attempt at a slightly more abstract definition:
Lexical scope:
The access or range something (e.g. a function or variable) has to other elements in the program as determined by its position in the source code.
Fwiw, my logic here simply builds from the definitions of:
Lexical: relating to the words or vocabulary of a language (specifically the word as separate from it's grammar or construction) {in our case - a programming language}.
Scope (noun): the range of operation {in our case the range is: what can be accessed}.
Note, the original 1960 definition of
Lexical Scope
from the ALGOL 60 spec is far more pithy than my attempt above:Lexical scope: the portion of source code in which a binding of a name with an entity applies. source
词法范围是指从执行堆栈中的当前位置可见的标识符(例如变量、函数等)的词典。
foo
和bar
始终位于可用标识符的词典中,因为它们是全局的。当执行
function1
时,它可以访问foo2
、bar2
、foo
和词典栏
。当执行
function2
时,它可以访问foo3
、bar3
、foo2
、bar2的词典
、foo
和bar
。全局和/或外部函数无法访问内部函数标识符的原因是因为该函数的执行尚未发生,因此其标识符尚未分配给内存。 更重要的是,一旦内部上下文执行,它就会从执行堆栈中删除,这意味着它的所有标识符都已被垃圾收集并且不再可用。
最后,这就是为什么嵌套执行上下文始终可以访问其祖先执行上下文,从而可以访问更大的标识符词典的原因。
请参阅:
特别感谢 @robr3rd 寻求帮助简化上述定义。
Lexical scope refers to the lexicon of identifiers (e.g., variables, functions, etc.) visible from the current position in the execution stack.
foo
andbar
are always within the lexicon of available identifiers because they are global.When
function1
is executed, it has access to a lexicon offoo2
,bar2
,foo
, andbar
.When
function2
is executed, it has access to a lexicon offoo3
,bar3
,foo2
,bar2
,foo
, andbar
.The reason global and/or outer functions do not have access to an inner functions identifiers is because the execution of that function has not occurred yet and therefore, none of its identifiers have been allocated to memory. What’s more, once that inner context executes, it is removed from the execution stack, meaning that all of it’s identifiers have been garbage collected and are no longer available.
Finally, this is why a nested execution context can ALWAYS access it’s ancestors execution context and thus why it has access to a greater lexicon of identifiers.
See:
Special thanks to @robr3rd for help simplifying the above definition.
围绕词法和动态作用域的对话中缺少一个重要部分:对作用域变量生命周期的简单解释 - 或者何时可以访问变量。
动态作用域只是非常松散地对应于我们传统上认为的“全局”作用域(我提出两者之间比较的原因是它已经提到 - 我不太喜欢链接文章的解释); 最好我们不要在全局变量和动态变量之间进行比较——尽管根据链接的文章,“...[它]可以作为全局范围变量的替代品。”
那么,简单来说,这两种范围界定机制之间的重要区别是什么?
词法作用域在上面的答案中已经被很好地定义了:词法作用域变量在定义它的函数的本地级别是可用的,或者是可访问的。
然而,由于它不是OP的重点,动态范围界定并没有受到很大的关注,而它所受到的关注意味着它可能需要更多的关注(这不是对其他答案的批评,而是“哦,这个答案让我们希望还有更多”)。 因此,这里还有更多内容:
动态作用域意味着在函数调用的生命周期内(或者在函数执行时),较大的程序可以访问变量。 确实,维基百科实际上在差异解释方面做得很好 两者之间。 为了不混淆它,下面是描述动态作用域的文本:
There is an important part of the conversation surrounding lexical and dynamic scoping that is missing: a plain explanation of the lifetime of the scoped variable - or when the variable can be accessed.
Dynamic scoping only very loosely corresponds to "global" scoping in the way that we traditionally think about it (the reason I bring up the comparison between the two is that it has already been mentioned - and I don't particularly like the linked article's explanation); it is probably best we don't make the comparison between global and dynamic - though supposedly, according to the linked article, "...[it] is useful as a substitute for globally scoped variables."
So, in plain English, what's the important distinction between the two scoping mechanisms?
Lexical scoping has been defined very well throughout the answers above: lexically scoped variables are available - or, accessible - at the local level of the function in which it was defined.
However - as it is not the focus of the OP - dynamic scoping has not received a great deal of attention and the attention it has received means it probably needs a bit more (that's not a criticism of other answers, but rather a "oh, that answer made we wish there was a bit more"). So, here's a little bit more:
Dynamic scoping means that a variable is accessible to the larger program during the lifetime of the function call - or, while the function is executing. Really, Wikipedia actually does a nice job with the explanation of the difference between the two. So as not to obfuscate it, here is the text that describes dynamic scoping:
古老的问题,但这是我的看法。
词法(静态)作用域是指源代码中变量的作用域。
在像 JavaScript 这样的语言中,函数可以传递、附加和重新附加到各种对象,您可能认为该范围取决于当时调用该函数的人,但事实并非如此。 以这种方式更改作用域将是动态作用域,而 JavaScript 不会这样做,除非可能使用
this
对象引用。为了说明这一点:
在示例中,变量
a
是全局定义的,但隐藏在doit()
函数中。 该函数返回另一个函数,如您所见,该函数依赖于其自身范围之外的a
变量。如果你运行这个,你会发现使用的值是
aardvark
,而不是apple
,尽管它在test()
的范围内> function,不在原始函数的词法范围内。 也就是说,使用的作用域是源代码中出现的作用域,而不是函数实际使用的作用域。这一事实可能会产生令人烦恼的后果。 例如,您可能认为单独组织函数更容易,然后在需要时使用它们,例如在事件处理程序中:
此代码示例执行其中一项操作。 您可以看到,由于词法作用域的原因,按钮
A
使用内部变量,而按钮B
则不使用。 您最终可能会嵌套更多的函数,超出您的预期。顺便说一句,在这两个示例中,您还会注意到,即使包含函数的函数已经运行完毕,内部词法作用域变量仍然存在。 这称为闭包,指的是嵌套函数对外部变量的访问,即使外部函数已经完成。 JavaScript 需要足够智能来确定这些变量是否不再需要,如果不需要,可以对它们进行垃圾回收。
Ancient question, but here is my take on it.
Lexical (static) scope refers to the scope of a variable in the source code.
In a language like JavaScript, where functions can be passed around and attached and re-attached to miscellaneous objects, you might have though that scope would depend on who’s calling the function at the time, but it doesn’t. Changing the scope that way would be dynamic scope, and JavaScript doesn’t do that, except possibly with the
this
object reference.To illustrate the point:
In the example, the variable
a
is defined globally, but shadowed in thedoit()
function. This function returns another function which, as you see, relies on thea
variable outside of its own scope.If you run this, you will find that the value used is
aardvark
, notapple
which, though it is in the scope of thetest()
function, is not in the lexical scope of the original function. That is, the scope used is the scope as it appears in the source code, not the scope where the function is actually used.This fact can have annoying consequences. For example, you might decide that it’s easier to organise your functions separately, and then use them when the time comes, such as in an event handler:
This code sample does one of each. You can see that because of lexical scoping, button
A
uses the inner variable, while buttonB
doesn’t. You may end up nesting functions more than you would have liked.By the way, in both examples, you will also notice that the inner lexically scoped variables persist even though the containing function function has run its course. This is called closure, and refers to a nested function’s access to outer variables, even if the outer function has finished. JavaScript needs to be smart enough to determine whether those variables are no longer needed, and if not, can garbage collect them.
通过退后一步并查看范围界定在更大的解释框架(运行程序)中的作用,我们可以得到关于这个问题的不同角度。 换句话说,想象一下您正在为一种语言构建一个解释器(或编译器),并负责在给定程序和一些输入的情况下计算输出。
解释涉及跟踪三件事:
状态 - 即堆和堆栈上的变量和引用的内存位置。
对该状态的操作 - 即程序中的每一行代码
环境给定操作运行 - 即状态在操作上的投影。
解释器从程序中的第一行代码开始,计算其环境,在该环境中运行该行并捕获其对程序状态的影响。 然后它按照程序的控制流执行下一行代码,并重复该过程直到程序结束。
计算任何操作的环境的方式是通过编程语言定义的一组正式规则。 术语“绑定”经常用于描述程序的整体状态到环境中的值的映射。 请注意,“整体状态”并不是指全局状态,而是指执行过程中任意时刻每个可到达定义的总和。
这是定义范围界定问题的框架。 现在我们的选择是什么的下一部分。
这是动态作用域的要点,其中任何代码运行的环境都绑定到由其执行上下文定义的程序状态。
换句话说,对于词法作用域,任何代码看到的环境都必须与在语言中显式定义的作用域(例如块或函数)相关联的状态。
Here's a different angle on this question that we can get by taking a step back and looking at the role of scoping in the larger framework of interpretation (running a program). In other words, imagine that you were building an interpreter (or compiler) for a language and were responsible for computing the output, given a program and some input to it.
Interpretation involves keeping track of three things:
State - namely, variables and referenced memory locations on the heap and stack.
Operations on that state - namely, every line of code in your program
The environment in which a given operation runs - namely, the projection of state on an operation.
An interpreter starts at the first line of code in a program, computes its environment, runs the line in that environment and captures its effect on the program's state. It then follows the program's control flow to execute the next line of code, and repeats the process till the program ends.
The way you compute the environment for any operation is through a formal set of rules defined by the programming language. The term "binding" is frequently used to describe the mapping of the overall state of the program to a value in the environment. Note that by "overall state" we do not mean global state, but rather the sum total of every reachable definition, at any point in the execution).
This is the framework in which the scoping problem is defined. Now to the next part of what our options are.
This is the gist of dynamic scoping, wherein the environment that any code runs in is bound to the state of the program as defined by its execution context.
In other words, with lexical scope the environment that any code sees is bound to state associated with a scope defined explicitly in the language, such as a block or a function.
范围是可以访问变量/绑定的上下文。 词法范围是指封闭的词法块或块的本地范围,而不是例如全局范围。
Scope is the context within which a variable/binding is accessible. Lexical scope means local to the enclosing lexical block or blocks as opposed to for instance global scope.
因此,要了解词法环境,我们首先要了解作用域的概念:
作用域:
因此,每当您在 javascript 中创建函数时,您都会创建一个作用域,这意味着该方法内的变量将无法访问从外面。
JavaScript 中可以有多个作用域。 首先也是最重要的,它具有全球范围。 然后假设您定义了函数
foo
,然后您拥有由foo
创建的作用域,现在您在 foo 中定义了另一个名为bar
的方法,然后您有另一个由bar
在foo
范围内创建的范围。现在,当我们在
bar
内部引用变量name
时,JavaScript 将不会在bar
内部找到任何内容,因此 javascript 将查找其外部foo
的范围并找到该变量然后使用它。这个作用域链称为作用域链。
现在词法环境基本上为您提供了这个作用域链以及一组关于如何使用它解析标识符的规则。 这总共称为函数的词法环境,在运行时用于解析标识符。
请记住,javascript 在编译阶段定义了此作用域,因此称为静态作用域。< /strong>
So to understand the lexical environment, let's understand the concept of scope first:
Scope:
So whenever you create a function in javascript you're creating a scope, Which means variables inside that method won't be accessible from outside.
There can be multiple scopes in javascript. First and foremost there's a global scope. Then let's say you define function
foo
, Then you have scope created byfoo
, and now you define another method inside foo by namebar
, Then you have another scope created bybar
inside the scope offoo
.Now when we make a reference to a variable
name
insidebar
, Then javascript will not find anything insidebar
, So javascript will look into its outer scope offoo
and find that variable and then use it.This chain of scopes is called a scope chain.
So now lexical environment basically provides you with this scope chain and a set of rules on how to resolve an identifier using it. This in total is called lexical environment of a function and is used during runtime to resolve an identifier.
Keeping in mind , javascript defines this scope during the compilation phase and hence is called static scoping.
该主题与内置
bind
函数密切相关,并在 ECMAScript 6 中引入 箭头函数。 这真的很烦人,因为对于我们想要使用的每个新“类”(实际上是函数)方法,我们必须绑定
它才能访问作用域。默认情况下,JavaScript 不会在函数上设置其
this
范围(它不会设置 上下文此
)。 默认情况下,您必须明确说明您想要的上下文具有。箭头函数自动获取所谓的词法范围(可以访问其包含块中的变量定义)。 使用 箭头函数 时,它会自动将
this
绑定到该位置其中首先定义了箭头函数,以及 context<此 箭头函数 的 /a> 是其包含块。通过下面最简单的示例来了解它在实践中是如何工作的。
在箭头函数之前(默认情况下无词法范围):
使用箭头函数(默认情况下词法范围):
This topic is strongly related with the built-in
bind
function and introduced in ECMAScript 6 Arrow Functions. It was really annoying, because for every new "class" (function actually) method we wanted to use, we had tobind
this in order to have access to the scope.JavaScript by default doesn't set its scope of
this
on functions (it doesn't set the context onthis
). By default you have to explicitly say which context you want to have.The arrow functions automatically gets so-called lexical scope (have access to variable's definition in its containing block). When using arrow functions it automatically binds
this
to the place where the arrow function was defined in the first place, and the context of this arrow functions is its containing block.See how it works in practice on the simplest examples below.
Before Arrow Functions (no lexical scope by default):
With arrow functions (lexical scope by default):
词法作用域意味着函数从定义它们的作用域解析自由变量,而不是从调用它们的作用域解析自由变量。
Lexical scoping means functions resolve free variables from the scope where they were defined, not from the scope where they are called.
我通常通过例子来学习,这里有一些东西:
I normally learn by example, and here's a little something: