Ara*_*raK 653
我通过例子理解它们.:)
首先,词典范围(也称为静态范围),采用类C语法:
void fun()
{
int x = 5;
void fun2()
{
printf("%d", x);
}
}
Run Code Online (Sandbox Code Playgroud)
每个内在级别都可以访问其外层.
还有另一种方法,称为动态范围,首先实现Lisp,再次使用类似C语法的语法:
void fun()
{
printf("%d", x);
}
void dummy1()
{
int x = 5;
fun();
}
void dummy2()
{
int x = 10;
fun();
}
Run Code Online (Sandbox Code Playgroud)
在这里fun既可以访问x的dummy1或dummy2,或x在调用任何函数fun与x在其声明.
dummy1();
Run Code Online (Sandbox Code Playgroud)
将打印5,
dummy2();
Run Code Online (Sandbox Code Playgroud)
将打印10.
第一个称为静态,因为它可以在编译时推断,第二个称为动态,因为外部作用域是动态的,取决于函数的链调用.
我发现静态范围对于眼睛更容易.大多数语言最终都是这样,甚至Lisp(可以做到这两种,对吗?).动态范围就像将所有变量的引用传递给被调用函数.
编译器无法推断出函数外部动态范围的一个例子,考虑我们的最后一个例子,如果我们写这样的东西:
if(/* some condition */)
dummy1();
else
dummy2();
Run Code Online (Sandbox Code Playgroud)
调用链取决于运行时条件.如果是,则调用链如下所示:
dummy1 --> fun()
Run Code Online (Sandbox Code Playgroud)
如果条件为假:
dummy2 --> fun()
Run Code Online (Sandbox Code Playgroud)
fun两种情况的外部范围都是调用者加上调用者的调用者等等.
只是提到C语言不允许嵌套函数或动态作用域.
Pie*_*ing 254
让我们尝试最短的定义:
词法范围定义如何在嵌套函数中解析变量名称:内部函数包含父函数的范围,即使父函数已返回.
这就是它的全部!
kta*_*kta 51
var scope = "I am global";
function whatismyscope(){
var scope = "I am just a local";
function func() {return scope;}
return func;
}
whatismyscope()()
Run Code Online (Sandbox Code Playgroud)
上面的代码将返回"我只是一个本地".它不会回归"我是一个全球化的".因为函数func()计算最初定义的位于函数whatismyscope范围内的位置.
它不会受到任何调用(全局范围/来自另一个函数)的困扰,这就是为什么全局范围值我是全局的不会被打印的原因.
这称为词法作用域,其中" 函数使用在定义时生效的作用域链来执行 " - 根据JavaScript定义指南.
词汇范围是一个非常强大的概念.
希望这可以帮助..:)
Ral*_*ach 38
范围定义了可用的功能,变量等区域.例如,变量的可用性在其上下文中定义,比如函数,文件或对象,它们是在中定义的.我们通常称这些局部变量.
词汇部分意味着您可以从阅读源代码中派生范围.
词法范围也称为静态范围.
动态范围定义了可在定义后从任何位置调用或引用的全局变量.有时它们被称为全局变量,即使大多数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.
Run Code Online (Sandbox Code Playgroud)
最接近Delphi的动态范围是RegisterClass()/ GetClass()函数对.有用,请看这里.
假设RegisterClass([TmyClass])被调用以注册某个类的时间无法通过读取代码来预测(它在用户调用的按钮单击方法中调用),调用GetClass('TmyClass')的代码将得到结果与否.对RegisterClass()的调用不必使用GetClass();在单元的词法范围内;
动态范围的另一种可能性是Delphi 2009 中的匿名方法(闭包),因为它们知道其调用函数的变量.它不会递归地跟随调用路径,因此不是完全动态的.
Sim*_*lGy 33
我喜欢@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
}
//...
};
Run Code Online (Sandbox Code Playgroud)
范围的另一种方法是使用Function.prototype.bind:
var downloadManager = {
initialize: function() {
$('.downloadLink').on('click', function () {
this.startDownload();
}.bind(this)); // create a function object bound to `this`
}
//...
Run Code Online (Sandbox Code Playgroud)
据我所知,这些方法在行为上是等同的.
Shi*_*pta 21
词法作用域意味着在嵌套的一组函数中,内部函数可以访问其父作用域的变量和其他资源。
这意味着子函数在词法上绑定到其父函数的执行上下文。
词法作用域有时也称为静态作用域。
function grandfather() {
var name = 'Hammad';
// 'likes' is not accessible here
function parent() {
// 'name' is accessible here
// 'likes' is not accessible here
function child() {
// Innermost level of the scope chain
// 'name' is also accessible here
var likes = 'Coding';
}
}
}
Run Code Online (Sandbox Code Playgroud)
您会注意到词法作用域是向前工作的,这意味着名称可以通过其子级的执行上下文访问。
但它不会向后返回到其父项,这意味着其父项likes无法访问该变量。
这也告诉我们,在不同执行上下文中具有相同名称的变量从执行堆栈的顶部到底部获得优先级。
最内层函数(执行堆栈的最顶层上下文)中名称与另一个变量相似的变量将具有更高的优先级。
来源。
Pra*_*hor 20
JavaScript 中的词法作用域意味着在函数外部定义的变量可以在变量声明之后定义的另一个函数内部访问。但事实并非如此。函数内部定义的变量将无法在该函数外部访问。
这个概念在 JavaScript 的闭包中被大量使用。
假设我们有以下代码。
var x = 2;
var add = function() {
var y = 1;
return x + y;
};
Run Code Online (Sandbox Code Playgroud)
现在,当您调用 add() --> 这将打印 3。
因此,add() 函数正在访问x在方法函数 add 之前定义的全局变量。这是由于 JavaScript 中的词法作用域而调用的。
J.K*_*.A. 17
在简单语言中,词法作用域是在您的作用域之外定义的变量,或者上层作用域在您的作用域内自动可用,这意味着您不需要将它传递到那里。
例子:
let str="JavaScript";
const myFun = () => {
console.log(str);
}
myFun();
Run Code Online (Sandbox Code Playgroud)
// 输出:JavaScript
Rob*_*cha 12
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();
Run Code Online (Sandbox Code Playgroud)
例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();
Run Code Online (Sandbox Code Playgroud)
词法作用域意味着函数在定义它的上下文中查找变量,而不是在它周围的作用域中查找变量。
如果您想了解更多细节,请查看Lisp 中词法作用域的工作原理。Kyle Cronin 在Common Lisp中的Dynamic and Lexical variables 中选择的答案比这里的答案清楚得多。
巧合的是,我只是在 Lisp 类中了解到这一点,它恰好也适用于 JavaScript。
我在 Chrome 的控制台中运行了这段代码。
// JavaScript Equivalent Lisp
var x = 5; //(setf x 5)
console.debug(x); //(print x)
function print_x(){ //(defun print-x ()
console.debug(x); // (print x)
} //)
(function(){ //(let
var x = 10; // ((x 10))
console.debug(x); // (print x)
print_x(); // (print-x)
})(); //)
Run Code Online (Sandbox Code Playgroud)
输出:
5
10
5
Run Code Online (Sandbox Code Playgroud)
词法范围是指从执行堆栈中的当前位置可见的标识符(例如变量、函数等)的词典。
\n\n- global execution context\n - foo\n - bar\n - function1 execution context\n - foo2\n - bar2\n - function2 execution context\n - foo3\n - bar3\nRun Code Online (Sandbox Code Playgroud)\n\nfoo并且bar始终位于可用标识符的词典中,因为它们是全局的。
执行时function1,它可以访问词典foo2、bar2、foo和bar。
执行时function2,它可以访问词典foo3, bar3, foo2, bar2, foo, 和bar。
全局和/或外部函数无法访问内部函数标识符的原因是因为该函数的执行尚未发生,因此其标识符尚未分配给内存。更重要的是,一旦内部上下文执行,它就会从执行堆栈中删除,这意味着所有 xe2\x80\x99s 标识符都已被垃圾收集并且不再可用。
\n\n最后,这就是为什么嵌套执行上下文始终可以访问它\xe2\x80\x99 的祖先执行上下文,从而可以访问更大的标识符词典。
\n\n看:
\n\n特别感谢@robr3rd帮助简化上述定义。
\n| 归档时间: |
|
| 查看次数: |
163826 次 |
| 最近记录: |