一个执行环境对应一个变量对象。在web浏览器中,全局执行环境的变量对象被认为是window对象。一个执行环境可以是看作是运行一个JavaScript函数时产生的内部空间,所有在这个函数内定义的变量和对象都挂载到这个函数的执行环境对应的变量对象上。
当我们的JavaScript程序运行时,每当调用一个函数,程序就将该函数的执行环境压入到程序维护的环境栈中,表示当前执行流进入了这个函数的执行环境。在函数中我们可能会调用某某变量,这时程序是怎么去查找这个变量的呢?首先从环境栈顶部的执行环境开始,从这个执行环境对应的变量对象中去查找变量,如果找到了,即说明某某变量是定义在这个函数中的,若没有找到
就会去当前执行环境的外执行环境对应的变量对象中查找,即环境栈中下一个执行环境的变量对象中查找,如果也找不到,继续到下一个执行环境,如此往复,直到找到为止。若一直到window对象也找不到,javaScript就会抛出错误, 即 xx is not defined。
如图所示,左边表示环境栈,右边表示变量对象之间的关系。一种不准确的说法,任何变量对象都有一个指向其父执行环境变量对象的“指针”,使得程序在当前执行环境找不到变量时,通过这个指针去查找下一个变量对象。
链式作用域:
在函数中定义的let变量,只能在函数中访问,在函数外无法访问。因为总是内部执行环境的变量对象维护指向外部执行环境变量对象的“指针”。当函数执行完毕后,对应的变量对象被回收,定义的变量也就不存在了。根据内部变量对象指向外部变量对象这一规则,我们可以得出一个结论,在外部执行环境中定义的变量,在内部执行环境中是可以访问到的,也确实符合JavaScript的语法规则。