js作用域

148 阅读2分钟

js作用域

可以理解为执行环境中变量或函数的作用范围,作用域定义了变量或函数有权访问的其他数据权限,作用域都有一个变量 具体分为以下三种

一、全局作用域

  1. 全局作用域在页面打开时被创建,页面关闭时被销毁
  2. 编写在script标签中的变量和函数,作用域为全局,在页面的任意位置可以访问到
  3. 全局作用域可以认为是window,因为所有的全局变量和函数都是作为window对象的属性和方法创建的
<script>
var a = 1 //全局作用域下变量
var fun = function () {} // 全局作用域下函数
</script>

二、局部(函数)作用域

  1. 函数调用时,函数作用域被创建,函数执行完毕,函数作用域被销毁
  2. 每调用一次函数就会创建一个新的函数作用域,他们之间是相互独立的
  3. 函数作用域可以访问上层作用域,但是相邻函数作用域之间是相互独立的
function fun () {
var a = 1
console.log(a)
}
fun() // 函数调用时函数作用域被创建,调用完毕函数作用域被销毁
function fun () {
var a = 1
a = a + 1
console(a)
}
fun() // 2
fun() // 2 两次输出均为2,函数每次调用重新创建作用域,相互独立
var b = 1
function fun () {
var a = 1
a = a + b
console.log(a)
}
function fun1() {
console.log(a)
}
fun() // 2,函数可以访问上级作用域b
fun1() // 报错 a 未定义

三、块级作用域(Es6)

Es6之前没有块级作用域,例如

if(true) {
var a = 2
}
console.log(a) // 2
  • 在{}(块级作用域)外仍可以访问到块级作用域里的内容 Es6可通过let和const实现块级作用域
<script>
    if(true){
      let i = 1
    }
    console.log(i); // 报错 i is not defined
    // 同样函数中也会有块级作用域
    function fun() {
    if(true){
      let i = 1
    }
    console.log(i) 
    } 
    fun() // 同样无法输出
  </script>
  • let fun = function() {}
  • console.dir(fun) 以上两行代码输出fun对象可以查看到let和const声明的变量是存储在块级作用域中

作用域链

作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。举例说明

var a = 1
    function fun() {
      var b = a + 1
      console.log(b);
    }
    fun()

从代码执行来看

首先在创建fun函数时,会预先创建一个包含全局变量对象的作用域链,这个作用域链被保存在内部的Scope属性中,当调用fun函数时 ,会为函数创建一个执行环境,然后通过复制函数的Scope属性中的对象构建起执行环境的作用域链,然后创建活动对象AO并推入执行环境的作用域链。在fun执行完毕后,作用域就会被销毁。