闭包、作用域链、变量提升大串联 - pod4g/tool GitHub Wiki

一. 名词解释

 变量对象也叫做作用域对象亦称词法环境(LexicalEnvironment),它们说的都是一个家伙。
 内部属性[scope](/pod4g/tool/wiki/scope)所指向的就是当前的作用域对象。也就是指的就是函数的标识符被创建的时候,
 我们所能够直接访问的那个作用域对象。

二. 闭包、作用域和作用域链、变量提升这3个javascript的特性都有一个本质:javascript引擎的2轮处理机制与执行环境。

三. javascript的2轮处理机制

  1. 创建阶段

    1. 声明并初始化函数参数
    2. 声明局部变量,包括将匿名函数赋值给一个局部变量,但并不会初始化他们
    3. 声明并初始化函数

在第一轮,局部变量并未被赋值,因为可能需要代码再执行之后才能确定它的值,而第一轮不会执行任何代码。参数被赋值了,因为在向函数传递参数之前,任何决定参数值的代码都已经运行了

  1. 执行阶段
 1. 执行代码,执行到赋值语句时赋予变量值

总结:

引擎的2轮处理机制,导致了变量提升

四. 从例子看执行环境对象

​function one() {

    var a = 1;
    two();

    function two() {

        var b = 2;
        three();

        function three() {

            var c = 3;
            alert(a + b + c); // 6

        }

    }

}

one()​;​

函数onetwothreeExecutionContextObject如下:


// global本身充当变量对象
// [scope](/pod4g/tool/wiki/scope) === ExcutionContextObject

globalExecutionContextObject = {
   
   // scopeChain: [global.variableObject],
   scopeChain: [global],

   variableObject: {
      one: pointer to one()
   }

   this: global

}

oneExecutionContextObject = {

   scopeChain: [one.variableObject, global],

   variableObject: {
       a: 1,
       two: pointer to two()
   },

   this:global

}

twoExecutionContextObject = {

   scopeChain: [two.variableObject, one.variableObject, global],

   variableObject: {
     b: 2,
     three: pointer to three()
   }

   this: global
 
}

threeExecutionContextObject = {

   scopeChain: [three.variableObject, two.variableObject, one.variableObject, global],
 
   variableObject: {
     c: 3
   },

   this: global

}


一道面试题

var a,b;
function test(){
  alert(a) // undefined
  alert(b) // undefined
  var a = b = 3
  alert(a) // 3
  alert(b) // 3
}
test()
alert(a) // undefined
alert(b) // 3

// 如果去掉 var a,b;
function test(){
  alert(a) // undefined
  alert(b) // 这一行报错,b not defined,然后退出
  var a = b = 3
  alert(a) 
  alert(b) 
}
test()
alert(a) 
alert(b) 

相关资料:

What is the Execution Context & Stack in JavaScript?

Identifier Resolution and Closures in the JavaScript Scope Chain

How do JavaScript closures work under the hood

scope内部属性

《单页web应用》第二章