JavaScript的作用域问题

JavaScript作用域应该是JavaScript里面最难理解的概念了。看了《JavaScript高级程序设计》和其他的书虽然费了很大力气看懂了,感觉解释的还是有点费解。正好在网上看到几个面试题可以用作用域解决,也方便了对它的理解。

1.JavaScript是单线程程序

和其他语言当初设计的时候不一样,JavaScript是单线程(一个时机段内只干一件事情),是不支持并发这个概念的。为什么会这样呢?可以这样理解,假如一个线程正在创建DOM对象,然后下面一个线程将DOM对象删除了,这样矛盾吗?另外一个问题就是现在很火的Node也是单线程。非常重要的是JavaScript的单线程对页面解析而言,从上到下。傻瓜式的执行。

2.JavaScript预解析机制

先来看一个程序的执行结果:

<code class="hljs delphi has-numbering">alert(a);<span class="hljs-comment">//function a(){alert(4);}</span>
<span class="hljs-keyword">var</span> a = <span class="hljs-number">1</span> ;
alert(a);<span class="hljs-comment">//1</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">a</span><span class="hljs-params">()</span><span class="hljs-comment">{alert(2);}</span>
<span class="hljs-title">alert</span><span class="hljs-params">(a)</span>;</span><span class="hljs-comment">//1</span>
<span class="hljs-keyword">var</span> a = <span class="hljs-number">3</span> ;
alert(a);<span class="hljs-comment">//3</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">a</span><span class="hljs-params">()</span><span class="hljs-comment">{alert(4);}</span>
<span class="hljs-title">alert</span><span class="hljs-params">(a)</span>;</span><span class="hljs-comment">//3</span></code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>

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,上面整个流程就分析完了。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。