深入理解作用域链

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解作用域链相关的知识,希望对你有一定的参考价值。

作用域链是javascript中的一个非常重要的概念,想要理解什么是作用域链,就必须知道什么是作用域。

作用域:

1、全局作用域:

  (1)最外层函数和在最外层函数定义的变量,拥有全局的作用域。js中一切皆对象,函数也是对象,js最外层的对象是window。所以在window下定义的函数和未被这些函数包裹的变量,就拥有全局作用域,这些变量能够在其他任何作用域下使用。

  (2)所有window对象下的内置属性属于全局变量:如window.document,window.navigator等。

  (3)没有通过var 定义,就直接赋值的变量,js会默认将其设置为全局变量,使其拥有全局作用域。

2、局部作用域:

  (1)在函数内部或者是事件句柄中的变量和函数拥有局部作用域。局部作用域下定义的变量只能在局部使用。

作用域链

     js函数也是对象,拥有可以访问的属性,以及js引擎访问的内部属性,其中Scope属性保存了当前函数可以访问的数据的集合。这个集合称之为作用域链。

  (1)、当函数被创建时,作用域链会首先填充一个全局对象,该全局对象会将所有的全局变量保存。然后作用域链会创建能够使用该函数的的作用域的变量的集合,如该函数的外层函数下的变量,该函数外层函数的外层函数的变量。并且最内层的集合会被推到作用域链的最顶端。此时全局对象会在作用域链的最末端。

   (2)、当函数在执行的时候,会创建一个“运行时上下文”的内部对象。这个内部对象定义了该函数执行时的环境。当“运行时上下文”被创建时,它会被初始化为当前函数的作用域链所有的对象,也就是定义函数时的作用域链会被赋值到该运行时的作用域链下。然后在该函数内部定义的局部变量会被赋值到该“运行时上下文”中,组成一个新的对象:"活动对象",也就是说活动对象保存了该函数下的局部变量。并将这个活动对象推向“运行时上下文”作用域链的顶端。

  (3)、当函数在执行完后,“环境运行时”时被销毁,这时的“活动对象”有两种情况

  1、活动对象因为无人引用而被释放。

  2、当活动对象中被引用,没有释放。函数的局部变量被保存。

3、作用域链域性能优化

  当函数在被执行的时候,每遇到一个变量都会从活动对象开始遍历解析,如果找到就使用该变量,如果没有找到就接着下一个变量找,在作用域链中都没有找到的话,这个值就是未定义的。

  所以我们知道了这个过程,在编写代码的时候尽量少定义全局变量,因为在一个局部作用域中使用全局变量的时候,总是会在最后查找全局变量,当函数嵌套很深的时候,遍历的过程就越长,对性能有一定影响。所以最好定义局部变量,而且出来性能之外,定义局部变量还有其他好处,如避免全局污染等。

注:本随笔的内容依据梦想天空(jzhula.com)而来,加入了自己的理解。如有不到位或者错误之处,烦请指出!

以上是关于深入理解作用域链的主要内容,如果未能解决你的问题,请参考以下文章

深入理解javascript中执行环境(作用域)与作用域链

JS深入理解闭包/作用域(scope)作用域链/执行上下文和执行栈

深入理解JavaScript系列(14):作用域链(Scope Chain)

深入理解javascript原型和闭包(14)——从自由变量到作用域链

JavaScript深入之作用域链(转)

变量对象+作用域链+闭包