深入理解Javascript范围的第二个词法范围和动态范围

在前面的话

大多数时候,我们混乱的范围的主要原因是,它是不清楚是否应该遵循功能位置的嵌套顺序或函数调用的顺序执行变量查找。对这一机制的干扰,变查找很容易出错。这实际上是由两种不同的域工作模式造成的。作用域分为词法范围和动态范围。划分这两个范围模型可以对变量搜索过程有一个清晰的认识,本文是对Javascript范围的第二部分——词汇范围和动态范围的深入理解。

词法范围

在第一个引言中,编译器的第一阶段称为分词,它是将一组字符分解成一个词汇单位,这个概念是理解词汇方法的范围的基础。

简单地说,词法范围是在词汇阶段定义的。它由写变量和块范围的位置决定。因此,当词法分析器处理代码时,它将保持不变。

关系

不管函数被调用的位置,不管调用的是什么,它的词法范围只由函数被声明的位置决定。


函数(a){
var b = a * 2;
函数条(c){
console.log(A,B,C);
}
酒吧(B * 3);
}
富(2 2412);


在这个示例中,有三个逐步嵌套的范围。为了帮助理解它们,可以将它们想象成若干个气泡级的气泡。

其中一个行动范围由其相应的域块代码决定,它们被一步一步地包含在其中。

气泡1包含整个全局范围,只有一个标识符:富

泡泡2包含了由富创建的范围,有三个标识符:A、bar和B

气泡3包含由bar创建的范围,只有一个标识符:C

查找

范围气泡的结构和位置关系为发动机提供足够的位置信息。引擎使用这些信息查找标识符的位置。

在这段代码的引擎执行console.log(…)的声明和查找引用三个变量A,B,和C,开始寻找最内部的范围,即范围,酒吧的功能(…)功能。发动机找不到这里,所以它会去上层为嵌套foo的范围(…),一个是在这里找到,所以引擎使用此参考。B C也是一样,发动机发现酒吧(…)

{词法范围查找将只查找第一级标识符。如果代码是指foo.bar.baz,词法范围查找将试图找到foo标识符。在找到的变量、对象属性访问规则以在酒吧和Baz属性的访问,分别。


{ { {
酒吧:{
Baz:1
}
};
console.log(foo。酒吧。巴兹); / / 1


庇护所

范围查找从运行时最内层的范围开始,逐步或向上,直到遇到第一个匹配标识符为止。

同一名称的标识符可以在多层嵌套范围中定义,称为阴影效应,内部标识符掩盖外部标识符。


var a=0;
函数测试(){
var a=1;
console.log(一); / / 1
}
测试();


全局变量自动归属于全局对象,因此可以通过引用全局对象直接访问,而间接引用全局对象属性。


var a=0;
函数测试(){
var a=1;
console.log(窗口。一个); / / 0
}
测试();


这种技术可以用来访问被相同名称变量掩盖的全局变量,但是如果一个非全局变量被遮挡,它就不能以任何速度访问。

动态范围

Javascript使用词法范围,其最重要的特性是它的定义过程发生在代码的编写阶段。

那么,为什么要引入动态范围呢事实上,动态作用域是Javascript的另一个重要机制的一个近亲,其作用范围的混乱主要是由于词法范围和机制的混淆。

动态作用域不关心函数和范围是如何在任何地方声明和声明的,只关心它们被调用的位置。换句话说,范围链基于调用堆栈,而不是嵌套在代码中的范围。


var a=2;
函数(){
console.log(一);
}
函数条(){
var a=3;
(富);
}
(酒吧);


{ { 1 }如果它在词法范围内,它是当前的Javascript环境。第一个变量是在()函数中找到的,并且没有找到。因此我们沿着操作链查找全局链,并找到并赋值值为2,因此控制台输出2。

{ 2 }如果在动态作用域中,变量A首先出现在富()中,并且没有找到。在这里,调用堆栈是在调用函数的地方,也就是bar()函数中找到并分配给3,所以控制台输出3。

总结:这两种行为的区别。简而言之,词法范围是在定义时定义的,动态范围是在操作时确定的。

以上是深入了解Javascript范围和动态范围的第二个范围,希望对您有所帮助。如果你想知道更多,请注意它。