理解JavaScript中的作用域链
发布时间:2016-10-30 06:27:17 所属栏目:教程 来源:站长网
导读:理解了作用域链,闭包就不难理解了,所以本文主要谈一谈我对作用域链的理解。关于JavaScript中变量的作用域,全局变量在程序中始终都有定义。局部变量在声明它的函数体内以及其内部所嵌套的函数内始终是有定义的。那么JavaScript是如何管理这些全局变量和局
|
理解了作用域链,闭包就不难理解了,所以本文主要谈一谈我对作用域链的理解。
关于JavaScript中变量的作用域,全局变量在程序中始终都有定义。局部变量在声明它的函数体内以及其内部所嵌套的函数内始终是有定义的。那么JavaScript是如何管理这些全局变量和局部变量作用域的呢,这就涉及到了作用域链。
作用域链相当于一个对象链表。链表的上的对象定义了这段script代码中的变量。如果要查找一个变量x,则会从这个作用域链的当前有权限访问的最底层对象开始找起,如果这个对象有一个名叫x的属性,则直接使用这个属性的值,如果没有找到继续向外层找其他的对象上是否有这个属性,直到找到作用域链的尾部,如果还没有,就返回undefined。
这里的“里层,外层”就是内部函数对包裹它的函数是不可访问的,提前说明一下有利于之后的理解。
在如下所示的JavaScript顶层代码中(不包含任何函数内定义的代码): 1 <script>
2 'use strict';
3 var a = "";
4 function hello(){
5
6 }
7 </script>
它的作用域链只包含一个全局对象,作用域链组成如下:
在这段script代码中,由于只有全局变量,所以只有一个全局作用域链。当我们需要寻找a变量或者是hello函数的时候,就会去这个全局作用域链上找可访问的最底层对象(也是仅有的一个对象)——全局对象,然后在他的属性中找是否有a属性或者hello属性。
以上我们看了只有全局作用域链的情况,下面我们看函数体内有变量的情况,这时候就变成了两个作用域链,代码如下所示: 1 <script>
2 'use strict';
3 var a = "";
4 function hello(){
5 var b = "";
6 console.log(b);
7 }
8 console.log(a);
9 hello();
10 </script>
此时我们注意到,hello函数的内部也定义了一个变量b,它的作用域链就变成了如下所示:
我们再看下面一段代码: 1 <script>
2 'use strict';
3 var scope = "global scope";
4 function checkscope(){
5 var scope = "local scope";
6 function f(){
7 return scope;
8 }
9 return f;
10 }
11 checkscope()();
12 </script>
最后的checkscope()();会返回什么呢?答案是“local scope”。这个地方如果想要理解,就必须借助作用域链。首先我们看一下这段代码的作用域链:
我们把“checkscope()()”分成两部分执行:
第一步:执行checkscope(),返回f函数,注意是函数不是结果。
第二步:执行f()函数,这时候我们发现函数f()是在全局环境下执行的,所以理所当然的想到返回“global scope”。其实不是这样子,从作用域链就能看出,f函数在“checkscope函数局部对象”上,所以它的可访问的最底层对象是“checkscope函数局部对象”,所以执行到“return scope”时找这个scope变量时会首先在checkscope函数局部对象上找,立马就找到了,所以结果返回“local scope”,假设找不到,才回去全局对象上找。
注意,作用域链只能由里往外找,不能由外往里找,这也是“闭包”实现原则。到此,如果能理解作用域链,则闭包也就不难理解了。
有错误的地方欢迎指出讨论! (编辑:宣城站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |



我们把“checkscope()()”分成两部分执行:
第一步:执行checkscope(),返回f函数,注意是函数不是结果。
第二步:执行f()函数,这时候我们发现函数f()是在全局环境下执行的,所以理所当然的想到返回“global scope”。其实不是这样子,从作用域链就能看出,f函数在“checkscope函数局部对象”上,所以它的可访问的最底层对象是“checkscope函数局部对象”,所以执行到“return scope”时找这个scope变量时会首先在checkscope函数局部对象上找,立马就找到了,所以结果返回“local scope”,假设找不到,才回去全局对象上找。
注意,作用域链只能由里往外找,不能由外往里找,这也是“闭包”实现原则。到此,如果能理解作用域链,则闭包也就不难理解了。
