执行上下文,调用栈,作用域链等


来自于对xiuyan文章的理解

执行上下文(执行代码的环境)

第一, 分类
全局上下文(全局代码所处的环境,不在函数中的代码都在全局执行上下文)
函数上下文(函数调用时创建的上下文)
eval上下文
第二,声明周期

  1. 全局上下文的创建和执行
    创建阶段(创建全局对象和this变量,将this指向全局变量,为变量和函数分配内存空间,给变量赋值为undefined,将函数声明放入内存,创建作用域链)
    执行阶段(逐行执行脚本里的代码)
  2. 函数上下文的创建和执行
    创建阶段:函数上下文在函数被调用时才会创建,创建的次数为被调用的次数,会创建一个参数对象(arguments),this指向被调用的对象,创建作用域链

理解变量提升
变量提升其实是因为全局上下文分为创建阶段和执行阶段,变量被创建后分配了内存空间并且赋值为undefined,但是还没有执行,所以所谓变量提升是执行上下文的正常现象。

调用栈

函数上下文在被调用时创建,在函数执行完后消失。
当我们调用一个函数时就会把它的上下文推入调用栈,执行完毕后出战,随后再为新的函数进行入栈操作。

当函数出站后,我们没办法访问到函数内部的变量,但闭包不是这样。因为当执行上下文被创建时,跟着被创建的还有作用域链,这个作用域链在函数中以内部属性形式存在,在函数定义是,其对应的父变量对象就会被记录到这个内部属性里。闭包正式通过这一层作用域链的关系,实现了对父作用域执行上下文信息的保留。
function outer(a){
return function inner(b){
return a+b;
}
}
var addA = outer(10);
addA(20);

外部作用域难以触及内部作用域,但是内部作用域可以访问外部作用域,这是为什么。
因为js引擎在函数内部找不到变量的时候,就会沿着作用域链往上走,去它的父级作用域链寻找直至找到。注意沿着作用域找,可不是沿着调用栈一层一层网上找,调用栈时执行过程中形成的,而作用域链是书写阶段决定了的。因此testB里找不到的变量,绝不会去testA里找,而是去全局上下文变量里找。

var name="lizzy";
function testA(){
  var name="zzj"
  console.log('执行testA');
  testB();
  console.log('执行testA第二次')
}
function testB(){
  console.log(name);
}