范围是变量或函数的执行背景,它定义了它可以访问的数据,这个概念看起来很简单,但它有一些重要的细微点。
JavaScript 传统上有两种类型的范围:全球范围和本地范围. 范围的目的是提供访问执行环境可以访问的所有变量和功能。
全球范围
当一个变量被宣布在任何函数之外时,它自动属于全球范围,并可以从程序中的任何地方访问,无论是函数还是任何块。
1const nestAnimal = 'crocodilian'; // belongs to the Global scope
2
3function getNestInfo(){
4 window.eggs = 5; // as well belongs to the Global scope
5}
事实上,在浏览器中,全球范围中的变量属于全球窗口
对象。
JavaScript是一種垃圾收集的語言,它在執行程式時保持所有變量在文脈中,然後刪除。讓我們考慮變量的生命週期。變量在函數執行過程中出現。變量在函數內使用,然後函數結束。在這個時刻,這個變量不再需要,所以它的記憶可以回收,JavaScript可以從記憶體中刪除這個變量。但是,整體變量在應用程式執行和堵塞的所有時間都留在記憶體中,這會減慢程式,也可能導致意外的名稱衝突。
这一切都意味着,只要有可能,你应该避免定义全球变量,它们只在非常具体的情况下真正需要,所以要小心这一点。
地方范围
ES6采用了使用const
和let
的关键字(LINK0
)的区块范围变量。使用这些关键字,创建了局部范围,并存在于周围最内在的区块中,它可以是一个函数,for
循环,while
区块,if
区块等。
每个区块都有自己的执行背景,它定义了它可以访问哪些数据,以及它应该如何行为。当代码在某个背景下执行时,创建了一个范围链,包括该区块内的所有声明变量和函数,然后来自包含(父母)背景的数据等。
让我们来看看一个例子:
1let caymanMood = 'calm';
2
3function changeMood(newMood){
4 if (caymanMood === 'calm'){
5 caymanMood = newMood;
6 } else {
7 caymanMood = 'calm';
8 }
9}
10
11changeMood('happy');
函数changeMood
有一个范围链,其中有两个对象:它自己的变量对象(参数对象newMood
)和全球背景的变量对象caymanMood
。
范围链增加
除了全球和本地执行环境之外,还可以扩展范围链,我们可以通过两种方式做到这一点。
- 1 点: A 与声明
- 2 点:在
试用...捕获
声明中的捕获
块
1function buildNest() {
2 const assets = 'grass';
3 with(reptilian){
4 const building = ability + assets;
5 }
6 return building;
7}
with
会创建一个被添加到范围链前面的对象,但是当你读到代码时,你无法确定哪个对象会被更改。 它会是全球变量ability
还是在这种情况下变量reptilian.ability
。 因此,程序的正确执行不能保证。 使用with
语句不建议 MDN web docs,因为它可能导致混淆的错误和兼容性问题。
catch
语句创建一个新的变量对象,其中包含投放错误对象的声明,并将此错误对象添加到范围链的前面。
包装上
有了这一点,您现在应该对JavaScript中的本地和全球范围如何工作,以及如何依靠最接近的本地背景是写易于阅读和可维护的代码的好主意略有更好的了解。