作用域、作用域链、词法作用域
在 JAVAscript 中,函数和对象都是变量,作用域决定了代码不同部分的变量的可访问性。
有趣的是,当我们开始更好地理解作用域时,我们可以在不同的作用域中使用相同的变量名,而不会发生任何冲突等等……
范围分为三种,
全球范围
在函数外部声明的变量称为全局范围,我们可以从代码的任何部分访问这些变量。
这里要注意的是我们可以访问在全局范围内声明的变量,在代码的任何范围内,如函数或块范围。
功能或本地范围
在函数内部声明的变量是局部作用域,我们无法在函数外部访问这些变量,这些变量仅限于该特定函数。
var bikeName = "Jarvis"; // declared in global scopefunction bikerDetails(){ var bikerName = "TTF"; // declared in functional or local scope console.log(bikerName + " loves " + bikeName);}bikerDetails();
在上面的代码中,bikeName是在全局范围内声明的,我们可以从代码的任何部分访问bikeName,变量bikerName是在bikerDetails函数内部声明的,我们不能从外部访问bikerName。
块范围
这是在 ES6 中引入的,大括号称为代码块,其中在块内使用 let 和 const 声明的变量只能在块内访问。
在 ES6 之前的传统 JavaScript 中,在 var 中声明的变量要么是函数作用域,要么是全局作用域,取决于它的声明位置,因此当花括号块不像其他语言那样形成作用域时,这可能会非常棘手和混乱。
const raining = 1;if(raining){ var action = "off the AC";}else{ var action = "let the AC run";}console.log(action);
在上面的 var 示例中,它是全局作用域,我们可以从代码的任何部分访问 var 操作,为了避免这种混淆,在 ES6 let 中,引入了 const 和块作用域。
const raining = 1;if(raining){ let action = "off the AC";}else{ let action = "let the AC run";}console.log(action);
在上面的代码中,控制台语句抛出了一个错误,因为变量 action 没有在全局范围内定义,我们试图在块范围内定义的全局范围内访问 action 变量。
与 var 不同,let 和 const 的作用域是最近的花括号,但如果我们在代码块中声明 var,我们可以从代码的任何部分(如全局作用域)访问该 var 变量。
{ var bikeName = "Jarvis"; let bikerName = "TTF";}console.log(bikeName); // jarvisconsole.log(bikerName); // throws not defined error
在上面的代码块中,由于 let 的行为, bikerName 会抛出一个错误,就像 let const 一样,行为是这样的。
当我们在声明时不将 var、let 或 const 放在变量的前缀中时,默认情况下它将作为 var 。
{ bikerFriend = "Ajeesh Bro";}
在上述场景中,变量 bikerFriend 的行为类似于 var 。
以上内容也适用于嵌套作用域,当前上下文的作用域可以访问父作用域的变量,它会搜索到全局作用域的变量,如果在全局作用域中没有找到该变量,那么它 引发参考错误,未定义。
嵌套范围
让我们考虑以下示例代码,
const bikeName = "Jarvis";function printBikeDetails() { function getBikerDetails() { function getBikeName() { return bikeName; } return getBikeName(); } return getBikerDetails();}console.log(printBikeDetails()); // Jarvis
在上面的嵌套范围中,我们从 getBikeName 函数返回了 bikeName 变量,其中 getBikeName 函数在自己的范围内搜索变量,如果没有找到,则在其父范围或其外部范围 getBikerDetails 中搜索,再次在父范围中搜索 ,直到找到bikeNamevariable,它一直在父范围内搜索,直到到达全局范围。
要记住的主要事情是范围是关于定义空间的,而不是关于调用空间的
上述在外部作用域中查找变量直至到达全局作用域的过程称为作用域链。
词汇环境
无论何时创建执行上下文 词法环境也被创建,词法环境是本地内存以及其父或外部范围的词法环境。
词汇意味着层次或顺序。
让我们考虑这个例子,
const bikeName = "Jarvis";function printBikeDetails() { function getBikerDetails() { function getBikeName() { return bikeName; } return getBikeName(); } return getBikerDetails();}console.log(printBikeDetails()); // Jarvis
内部函数 getBikeName 可以访问 getBikerDetails 的词法环境,就像 getBikerDetails 可以访问 printBikerDetails 的词法环境一样,其中 printBikerDetails 可以访问全局范围。
通过使用作用域链和词法环境,当本地作用域中不可用时,我们可以从父作用域访问变量。