JavaScript的作用域和上下文

作用域在函数定义时就已经确定了,执行上下文环境在函数调用时才确定。在全局作用域和函数作用域中会创建执行上下文环境(有闭包存在时,一个作用域存在两个上下文环境也是有的)。函数每调用一次都会产生一个新的执行上下文环境。但是处于活动状态的执行上下文环境只有一个,这是一个压栈出栈的过程。

执行上下文:函数每调用一次,都会产生一个新的执行上下文环境,因为不同的调用可能就有不同的参数。

let a = 10, fn,       // 1、进入全局上下文环境
     bar = function(x) {
         let b = 5
         fn(x + b)     // 3、进入fn函数上下文环境
     }
fn = function(y) {
    let c = 5
    console.log(y + c)
}

bar(10)                 // 2、进入bar函数上下文环境

首先(数字1注释),执行代码之前,首先创建全局上下文环境(活动状态)如下:

// 全局上下文环境
a: undefined
fn: undefined
bar: undefined
this: window

之后开始执行代码,代码到10行之前,上下文环境中的变量都在执行过程中被赋值如下:

// 全局上下文环境
a: 10
fn: function
bar: function
this: window

然后执行到bar(10) ,跳转到bar函数内部,执行函数体语句之前,在bar函数内会创建一个新的执行上下文环境如下,并且将bar执行上下文环境压栈。

// bar执行上下文环境
b: undefined
x: 10
arguments: [10]
this: window

然后执行到数字3注释那里,调用fn函数,执行函数体语句之前,会创建一个新的执行上下文环境如下,并且将fn执行上下文环境压栈。

// fn执行上下文环境
c: undefined
y: 15
arguments: [15]
this: window

在上边步骤中,fn执行完毕后,调用fn函数生成的fn上下文环境出栈,被销毁。然后bar执行完毕后,调用bar函数生成的上下文环境出栈,被销毁。然后剩下全局上下文环境,出栈销毁。具体步骤如下图:

作用域:JavaScript 采用的是词法作用域,即函数的作用域在函数定义的时候就决定了,在外部作用域无法访问内部作用域中的变量。

作用域链:如果要取得一个变量得值,首先会在当前的作用域中寻找,如果没有,就会到外层作用域中寻找,再没有在向外层的作用域中找,找到了就结束了,找不到就报异常了,就形成了作用域链。

每个函数作为一个作用域,如果出现函数嵌套函数,则就会出现作用域链。JavaScript的作用域在被执行之前已经创建,之后后再去执行时只需要按照作用域链去寻找即可。

自由变量:比如变量a,是在fn函数作用域使用,但是并没有在fn作用域声明,而是在别的作用域声明,这就是自由变量。

 

posted @ 2019-08-28 12:12  seeBetter  阅读(126)  评论(0编辑  收藏  举报