深入浅出JavaScript执行环境
JavaScript执行环境是非常重要的一个概念,理解执行环境对JS的原型(prototype),作用域(scope)以及作用域链能有更深刻的理解。
执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为,JS执行环境主要分为全局执行环境以及函数执行环境。探清两种执行环境的虚实以及弄懂它们之间的关系,相信你会在以后有的JS代码开发中更能得心应手。
一、全局执行环境
在Web浏览器中,全局执行环境被认为是Windows对象。当谈到Windows对象,我们就必须要理清(不能瞎摸)什么是BOM了,BOM其实就是通过JavaScript操作浏览器的一个接口,可以通过BOM打开、关闭浏览器窗口等。BOM的核心就是Windows对象,这个对象定义了很多的方法,用来与浏览器进行各种交互。
所以,全局执行环境就具有这些方法了,调用的方式即window.*(w小写哦)。所以任何的JS代码都具有全局执行环境。说了这么多,没代码怎么行呢!
//我们简单定义一个变量和函数
var a = 12;
function test(){
console.log(a);
}
代码相信同学们都看得懂,无非就是定义了一个变量和函数,但是定义的变量和函数都在全局的执行环境中,我们可以通过window.a和window.test()访问a的值和运行test函数。所以他们都是全局执行环境中的变量和方法,建议大家在以后的开发中尽量少定义全局变量和方法哦,这样会污染全局执行环境,给团队开发会带来巨大的困扰的。
二、函数执行环境
顾名思义,函数执行环境只有在函数声明时才会创建哦,当我们创建一个函数,它的执行环境就会被创建出来,我们可以看看一下的代码:
function a(){
var m = 10;
function b(){
var n = 20;
}
};
var c = new Funcion();
以上代码中,首先定义了一个函数a,在a中再定义了一个函数b,容易理解,这里就有两个函数的执行环境,我们可以把这个执行环境的范围叫作用域,这里就不再展开叙述了,有兴趣的同学可以看我的另一篇作用域的博文。
那么问题来了,以上代码中的c是在全局执行环境还是在函数执行环境中呢?
这里我们就要理解代码的执行情况了,学了其他语言如C/C++,JAVA等语言的同学应该知道,在一个程序运行时主要分为两个阶段:预处理阶段与执行阶段,在预处理阶段,后台会创建一个执行环境(就是上面讲到的执行环境哦,有时也称为上下文Context,词法环境Lexcical Environment),用于存储通过正式声明的变量或函数(此处的正式声明指的是通过var,function等关键字声明的函数或变量),需要注意的是:arguments对象也在里面。预处理阶段与执行阶段的主要区别就是预处理阶段处理的只是函数或变量的声明,执行阶段处理的是函数的赋值以及计算等。
var color = 'red';
function changeColor(){
if(color == 'red'){
color = 'red';
} else {
color = 'blue';
};
} ;
var name = function(){
console.log("My name is WangLaoWu!")
}
我们开始分析以上代码吧:
在预处理阶段:定义了一个全局变量color,两个函数changeColor和a,所以在这个阶段只处理声明var和function,所以预处理阶段只能告知程序用var声明了color和a,它们都没被赋值,即undefined;以及用function声明了一个changeColor函数,它是一个指向函数的引用。我们可以通过在后台输出这些值以验证正确性,即在函数声明之前通过console.log()方法输出结果。而在执行阶段,变量和函数都已被正确赋值,可以通过正常的输出调用得到结果。
<script>
console.log(color); //undefined
console.log(name); //undefined
console.log(changeColor); //function b()...
var color = 'red';
function changeColor(){
if(color == 'red'){
color = 'red';
} else {
color = 'blue';
};
} ;
var name = function(){
console.log("My name is WangLaoWu!")
}
console.log(color); //red
</script>
在JS领域中,代码不会按从上到下的顺序执行,所以请同学们不要想当然地将上述代码认为在开始用console.log()输出的任何东西都认为结果是undefind,如changeColor,如果没有下面定义的function changeColor()…,它的结果的确是undefined。所以可以理解为在程序运行前,首先进行的是预处理阶段,处理并识别所有的函数执行环境与全局执行环境,并将通过正式定义的变量或函数添加到这个执行环境中去,然后再进行程序的执行。