JavaScript作用域应该是JavaScript里面最难理解的概念了。看了《JavaScript高级程序设计》和其他的书虽然费了很大力气看懂了,感觉解释的还是有点费解。正好在网上看到几个面试题可以用作用域解决,也方便了对它的理解。
1.JavaScript是单线程程序
和其他语言当初设计的时候不一样,JavaScript是单线程(一个时机段内只干一件事情),是不支持并发这个概念的。为什么会这样呢?可以这样理解,假如一个线程正在创建DOM对象,然后下面一个线程将DOM对象删除了,这样矛盾吗?另外一个问题就是现在很火的Node也是单线程。非常重要的是JavaScript的单线程对页面解析而言,从上到下。傻瓜式的执行。
2.JavaScript预解析机制
先来看一个程序的执行结果:
alert(a);//function a(){alert(4);}
var a = 1 ;
alert(a);//1
function a(){alert(2);} alert(a);//1
var a = 3 ;
alert(a);//3
function a(){alert(4);} alert(a);//3
JavaScript解析器在解析的代码的时候可以简单的分为两个步骤(结合上述代码):
第一步:遍历代码寻找var变量、function函数、参数
a.将所有的var变量设置为undefined
- a = undefined
b.将所有的函数体赋值给函数指针
- a = function a(){alert(2);}
- a = function a(){alert(4);}
c.整合上述两个步骤,其中+-*/%等具有运算功能进行赋值,后面的会覆盖前面的,所以上面的a、b两个步骤执行完过后就剩下:
- a = function a(){alert(4);}
第二步:逐行扫描代码
在逐行扫描的过程中,会随时查看第一步中计算的结果a = function a(){alert(4);} 同时我们知道运算符具有赋值功能,会修改变量的值,而函数不具有赋值的功能。执行第一行代码alert(a)
发现第一步执行结果是a = function a(){alert(4);}
所以alert(a)的结果是 function a(){alert(4);}
扫描第二行var a = 1;
发现有=具有赋值功能可以修改变量的值从而将a变量修改为var a = 1;
扫描第三行发现现在有var a = 1;
所以alert(a)
结果是1,扫描第四行代码function a(){alert(2);}
发现是函数所以没有赋值的功能。无法修改变量的值。所以第五行代码alert(a)
的执行结果是1。扫描第六行代码var a = 3 ;
所以变量a被修改为var a = 3 ;
第七行代码执行结果是3;扫描第八行代码发现是函数function a(){alert(4);}
无法修改变量的值,所以下面alert(a)
执行的结果是3,上面整个流程就分析完了。
(这里不探讨所谓的语法、词法这些编译原理方面的知识)
3.JavaScript作用域链的简单理解
先看下面这个笔试题目:
var str = 'jQuery';
function fun(){
alert(str);//jQuery
str = 'JavaScript';
}
fun();
alert(str);//JavaScript
按照上面将的两步方法进行分析,第一步:先找var变量、function函数、参数
var str = undefined
fun = fun(){………..}
第二步:逐行扫描代码第一行将变量str
修改为var str = 'jQuery';
第二行行数没有赋值功能,第六行是函数调用,只要发生函数调用,继续第一步寻找变量、函数和参数,发现没有var变量函数和参数,这个时候将向函数外层寻找变量,这就是作用域链的概念,里面没有继续向外层寻找变量。发现有变量var str = 'jQuery';
所以结果是jQuery
,向下执行代码str = 'JavaScript'
操作符号可以进行赋值,发现外部有str同名变量所以有var str = 'JavaScript'
,所以最后一行执行结果是JavaScript
。
以上就是今天的内容,内容不多但是不是很好理解。建议多分析多思考。和实际案例结合。。。实践出真知!
非常高兴和大家交流学习
*转载,创意许可,请文章来源,来自这里
(http://blog.csdn.net/unikylin)