var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
猜猜这两端代码运行结果是什么,其实都是“local scope”,哪产生这样的原因是什么了。
在《JavaScript权威指南》中给出的解释是:JavaScript函数的执行使用到了作用域链,这个作用域链是在函数定义的时候的创建的。也就是编译器编译的时候就创建好的。 在JavaScrip中作用域,采用的是词法作用域(PS:定义在词法阶段的作用域。词法作用域是由你在写代码时将变量和块级作用域写在哪决定的。)。嵌套函数f(),定义在作用域链中,其中变量scope是一个局部变量,绑定在f()上,不管何时执行f(),这个绑定依然是有效的。
虽然这两端代码执行不一样,但是究竟有什么不同了。引发思考!
在JavaScrip中,引擎执行代码,并非完全一行一行的执行,而是一段一段(在JavaScript中一段一段可执行代码,可以分为三类,全代码,函数代码,eval代码。)的分析和执行的,当代码执行一段代码,就会进行一个“准备工作”,“准备工作”就是执行上下文。
在JavaScript中,会创建很多执行上下文,哪JavaScript是如何管理执行上下文的了,其实是使用一个执行上下文栈来进行管理的,当执行一个函数的时候,就会创建一个执行上下文,并且压如到执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文栈中弹出。
我们在回头来看上面引发思考的代码。
代码一运行过程:ECStack执行上下文栈
ECStack.push(全局上下文)
ECStack.push(checkscope上下文)
ECStack.push(f上下文)
ECStack.pop(f上下文)
ECStack.pop(checkscope上下文)
ECStack.pop(全局上下文)
代码二运行过程:ECStack执行上下文栈
ECStack.push(全局上下文)
ECStack.push(checkscope上下文)
ECStack.pop(checkscope上下文)
ECStack.push(f上下文)
ECStack.pop(f上下文)
ECStack.pop(全局上下文)
是不是有些不一样,执行上下文的入栈和出栈顺序不太一样。如果可以更深入,将讨论引擎和编译器为什么会产生这样的效果。