手机版

JavaScript范围链解析

时间:2021-09-09 来源:互联网 编辑:宝哥软件园 浏览:

JavaScript中有一些概念,比如范围、范围链、执行上下文、活动对象、动态范围和闭包。要理解这些概念,我们应该从静态和动态两个方面进行分析。

首先,让我们写一个简单的函数来举一个例子:

复制代码如下:函数add (num1,num 2){ var sum=num 1 num 2;返回总和;}

我们用两个形式参数定义一个加法函数。

静态方面:

创建add函数时,Javascript引擎将创建add函数的作用域链,该作用域链指向全局上下文。如果使用下图所示的图形表示:

从上图可以看出,在创建add函数时,已经创建了作用域链,因此可以得出结论,函数的作用域链是在创建函数时创建的,而不是动态运行时。让我们看看在动态运行时发生了什么。

动态方面:

当执行add函数时,JavaScript将创建一个Execute上下文,其中包含add函数在运行时所需的所有信息。执行上下文也有自己的范围链。函数运行时,JavaScript引擎将首先用add函数的作用域链初始化执行上下文的作用域链,然后JavaScript引擎将创建一个Active Object,它包含函数运行时的所有局部变量、参数和这个变量。

如果你形象地描述add函数动态运行期间发生的事情,可以用下图来描述:

从上图可以看出,执行上下文是一个动态概念,是函数运行时创建的,Active Object对象也是一个动态概念,由执行上下文的作用域链引用。由此可以得出一个结论:执行上下文和活动对象都是动态概念,执行上下文的范围链由函数范围链初始化。

上面提到了函数范围和执行上下文范围,然后讨论了动态范围。当JavaScript传递catch语句、try-catch子句和eval方法时,JavaScript引擎会动态改变执行上下文的范围。让我们看看下面的一个例子:

复制代码如下:函数init ui(){ with(document){//避免!var bd=body,links=getElementsByTagName('a '),i=0,len=links.lengthwhile(I len){ update(link[I]);} getElementById('go-btn ')。onclick=function(){ start();};bd.className=' active}

在执行上面的initUI函数时,JavaScript会动态创建一个与with语句对应的作用域,并将其放在执行上下文作用域链的前面。上面的过程可以用下图形象地描述出来,下图中用红色标记的区域显示了with语句生成的范围。

最后,让我们来看看JavaScript中最神秘的闭包。闭包实际上是JavaScript中的一个函数,闭包是在函数运行时创建的。让我们举一个例子:

复制代码如下:函数赋值事件(){ var id=' xdi9592document . getelementbyid(' save-BTN ')。onclick=function(event){ SaveDocument(id);};}

当执行上述assignEvents函数时,将创建一个闭包,这个闭包将引用assignEvents作用域中的id变量。如果按照传统的编程语言,id是一个存储在栈上的变量,函数执行后id就消失了,怎么还能再次引用呢?显然,JavaScript在这里采用了另一种方法。让我们来看看JavaScript是如何实现闭包的。在执行assignevents函数时,JavaScript引擎会创建一个assignEvents函数执行上下文的范围链,其中包含了assignEvents执行过程中的活动对象,同时,JavaScript引擎会创建一个闭包,闭包的范围链也会引用assignEvents执行过程中的活动对象。这样,在执行assignEvents时,虽然其自身执行上下文的作用域链不再引用活动对象,但闭包仍然引用与assignEvents运行时对应的活动对象,这就解释了JavaScipt内部的闭包机制。您可以使用下图来描述上述分配事件函数的运行时情况:

从上面可以看出,在执行了assignEvents函数之后,document . getelementbyid(' save-BTN ')。onclick指的是闭包,所以当用户点击save-BTN时,闭包将被触发执行。那么我们来看看执行闭包时的情况。前面说过,JavaScript中的闭包实际上是一个函数,所以闭包执行时的情况和函数执行时的情况是一致的。下图生动地描述了与上述onclick事件相关联的闭包。

从上图可以看出,JavaScript引擎首先创建闭包的执行上下文,然后用闭包作用域链初始化闭包的执行上下文作用域链,最后将闭包对应的活动对象放在作用域的前面,进一步验证了闭包是函数的断言。

版权声明:JavaScript范围链解析是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。