var a=10; function fn(){ console.log(a) } function bar(f){ var a=20; f(); } bar(fn)
函数每被调用一次,都会产生一个新的执行上下文环境。
函数在定义的时候(不是调用的时候),就已经确定了函数体内部自由变量的作用域。
首先,我们如何创建一个作用域呢,function()。除了全局作用域,只有函数才能创建作用域,也就是说for、if、while的{}是不能创建出作用域的。区别c++中的块作用域{}。
一个函数的作用域创建后,将贯穿他的始“{”,终“}”,作用域在函数创建时被存储,与函数共存亡。
这句话就应该着重理解贯穿2字了,若函数内部嵌套着多个函数,那么从最内层函数作用域依次往外就形成了作用域链。
ps:需要我们理解作用域链的变量查找机制是由内往外的。先找自身作用域,再一次往外,若没有,则等同没有var时的声明(为全局添加了一个属性);
作用域链正是内部上下文所有变量对象(包括父变量对象)的列表。
一个作用域下可能包含若干个上下文环境。有可能从来没有过上下文环境(函数从来就没有被调用过);有可能有过,现在函数被调用完毕后,上下文环境被销毁了;有可能同时存在一个或多个(闭包)。
执行完第17行,fn(5)的返回值赋值给了f1。此时执行上下文环境又重新回到全局,但是fn(5)的上下文环境不能就此销毁,因为其中有闭包的引用
执行第18行,再次调用fn函数——fn(10)。产生fn(5)的上下文环境,并压栈,并设置为活动状态。但是此时fn(5)的上下文环境还在内存中——一个作用域下同时存在两个上下文环境。