作用域
● 作用域(Scoping):我们程序中变量的组织和访问方式。"变量存在在哪里?“或者"我们可以在哪里访问某个变量,以及在哪里不能访问?”
● 词法作用域(Lexical scoping):作用域由函数和代码块的位置控制。
● 作用域(Scope):变量声明的空间或环境(在函数的情况下是变量环境)。有全局作用域、函数作用域和块作用域:
● 变量的作用域:代码中可以访问某个变量的区域。
三种类型的作用域
全局作用域
const me = "ItShare";
const job = "teacher";
const year = 1999;
● 在任何函数或块之外
● 在全局作用域中表明的变量在任何地方都可以访问
函数作用域
function calcAge(birthYear) {
const now = 2037;
const age = now - birthYear;
return age;
}
console.log(now);//ReferenceError
● 变量只能在函数内部使用,不能在函数外部访问
● 也称为局部作用域
块作用域
● 变量只能在块内访问(块级作用域)
● 然而,这仅适用于使用let和const声明的变量!
● 函数也是块级作用域的(仅在严格模式下)。
作用域案例
const myName = 'Jonas';
function first() {
const age = 30;
if (age >= 30) {
// true
const decade = 3;
var millennial = true;
}
function second() {
const job = 'teacher';
console.log(`${myName} is a ${age}-old ${job}`);
// Jonas is a 30-old teacher
}
second();
}
first();
作用域链和调用堆栈的关系
总结
● 作用域提出这样一个问题:“变量存在于何处?” 或者"我们在哪里可以访问某个变量,在哪里不可以?"
● 在JavaScript中有三种作用域:全局作用域、由函数定义的作用域以及由块定义的方位(ES6开始);
● 只有let和const变量是块作用域的,用var声明的变量在最近的函数作用域中结束;
● 在JavaScript中,我们有词法作用域,所以我们可以访问变量的规则是基于函数和块在代码中的确切位置编写的;
● 每个作用域总是可以访问其外层作用域中的所有变量。这就是作用域链!
● 当一个变量不在当前作用域中时,引擎会沿着作用域链向上查找,直到找到所需的变量。这被称为变量查找;
● 作用域链是单向的:一个作用域永远不会访问内部作用域的变量。
● 在某个作用域中的作用域链等于将所有父作用域的变量环境相加。
● 作用域链与函数调用的顺序无关。它对作用域链没有任何影响!