理解js中的做用域

执行期上下文(AO):函数在运行时(或预编译时),会建立一个叫执行期上下文问的一个内部对象Activation Object(全局的叫Global Object)。AO或GO,他定义了一个函数的执行环境(用来作变量/函数的提高等等),函数执行完毕则会销毁。es6

做用域:每个函数对象都有一个[[scope]]属性,他内部存储了执行期上下文的集合,也就是咱们说的做用域。这个集合是一种链式结构,叫作做用域链bash

做用域链的造成过程

  • 当函数被定义时,这个函数的[[scope]]属性会指向它的上一级函数的[[scope]]属性的值的引用
  • 当函数被执行时,这个函数的[[scope]]属性会在他的最上层添加他本身的执行期上下文(AO)。
  • 当函数执行完成后,他本身的执行期上下文(AO)会被销毁
  • 当查找某个变量或方法时,会从[[scope]]属性的最上层一直向下寻找。即先找它本身的AO,若未找到,则再向他的上一级函数的寻找

举个栗子:函数

function a(){
    function b(){
    	var b = 123
    }
    var a = 10
    b()
}
var glob = 100
a()
复制代码

1.a函数定义时,它的[[scope]]会指向它的上一级即全局的执行期上下文(GO) ui

在这里插入图片描述
2.a函数执行时,他的[[scope]]会在他的最上层(最首位)添加本身的执行期上下文(AO),其祖先级依次下移(后移)。
在这里插入图片描述
3.此时,b函数被定义,它的scope属性指向它的上一级,即a的scope的引用。
在这里插入图片描述
4.b函数被执行时,会造成本身的AO,并置于其做用域链的最顶端(首部),其他依次下移(后移)。
在这里插入图片描述
5.此时,当某个函数内使用某个变量时,会在其做用域链上(scope chain)依次寻找. 注:一个函数得AO对象上,还包括this、arguments等属性,此处不一一介绍

做用域的分类

全局做用域:全局做用域指的是在全局起做用的做用域。通常指上面所说的GOthis

局部做用域(函数做用域):局部做用域指的是在局部起做用的做用域。通常函数的做用域都是局部做用域,即上面的AO。es5

块做用域:通常而言,块做用域指的是以{}包含的内容快,函数或变量只在它所在的的快内起做用。es5中不存在块做用域,es6新增了块做用域。for循环和if语句的{}属于块做用域spa

举个例子 当咱们使用if语句时,在if语句的内部定义了变量3d

var foo = true
if(foo){
    var c = 2
    console.log(c) // 2
}
console.log(c)  // 2
复制代码

变量c只在if所在的代码块中使用,所以将他声明在if语句内部是很必要的,可是经过var声明的变量最终都会属于外部做用域。至关于如下代码code

var foo = true
var c
if(foo){
    c = 2
    console.log(c) // 2
}
console.log(c)  // 2
复制代码

因此就须要一些其余的结构或语法来实现块级做用域。在es6中新增了let/const,用来声明变量 let会把变量绑定在它所在的块中。 const用来声明常量,也会造成块级做用域。cdn

var foo = true
if(foo){
    let c = 2
    console.log(c)
}

console.log(c)  // 报错
复制代码

因为let会造成块级做用域,因此if(){}外接受不到c变量,因此会报错

相关文章
相关标签/搜索