作用域(scope)
1.什么是作用域
概念:作用域是在程序运行时代码中的某些特定部分中变量、函数和对象的可访问性。
从使用方面来解释,作用域就是变量的使用范围,也就是在代码的哪些部分可以访问这个变量,哪些部分无法访问到这个变量,换句话说就是这个变量在程序的哪些区域可见。代码演示:
function Fun() {
var inVariable = "内部变量";
}
Fun();
console.log(inVariable); // Uncaught ReferenceError: inVariable is not defined
//inVariable是在Fun函数内部被定义的,属于局部变量,在外部无法访问,于是会报错
从存储上来解释的话,作用域本质上是一个对象, 作用域中的变量可以理解为是该对象的成员
总结:作用域就是代码的执行环境,全局作用域就是全局执行环境,局部作用域就是函数的执行环境,它们都是栈内存
2.作用域分类
作用域又分为全局作用域和局部作用域。在ES6之前,局部作用域只包含了函数作用域,ES6的到来为我们提供了 ‘块级作用域’(由一对花括号包裹),可以通过新增命令let和const来实现;而对于全局作用域这里有一个小细节需要注意一下:
- 在 Web 浏览器中,全局作用域被认为是
window
对象,因此所有全局变量和函数都是作为window
对象的属性和方法创建的。- 在 Node环境中,全局作用域是
global
对象。
全局作用域很好理解,现在我们再来解释一下局部作用域吧,先来看看函数作用域,所谓函数作用域,顾名思义就是由函数定义产生出来的作用域,代码示例:
function fun1(){
var variable = 'abc'
}
function fun2(){
var variable = 'cba'
}
fun1();
fun2();
//这里有两个函数,他们分别都有一个同名变量variable,在严格模式下,程序不会报错,
//这是因为这两个同名变量位于不同的函数内,也就是位于不同的作用域中,所以他们不会产生冲突。
我们再来看看块级作用域,ES6 之前 JavaScript 没有块级作用域,只有全局作用域和函数(局部)作用域。块语句( {}
中间的语句),如 if
和 switch
条件语句, for
和 while
循环语句,不同于函数,它们不会创建一个新的作用域;但是ES6及之后的版本,块语句也会创建一个新的作用域, 块级作用域可通过新增命令let和const声明,所声明的变量在指定块的作用域外无法被访问。块级作用域在如下情况被创建:
- 在一个函数内部
- 在一个代码块(由一对花括号包裹)内部
let 声明的语法与 var 的语法一致。基本上可以用 let 来代替 var 进行变量声明,但会将变量的作用域限制在当前代码块中 (注意:块级作用域并不影响var声明的变量)。 但是使用let时有几点需要注意:
- 声明变量不会提升到代码块顶部,即不存在变量提升
- 禁止重复声明同一变量
- for循环语句中()内部,即圆括号之内会建立一个隐藏的作用域,该作用域不属于for后边的{}中,并且只有for后边的{}产生的块作用域能够访问这个隐藏的作用域,这就使循环中 绑定块作用域有了妙用
参考 前端进阶面试题详细解答
这里分别演示一下ES5和ES6版本的代码,ES5:
if(true) {