这几天看了一下JS高级程序设计里的介绍做用域的章节,也参考了网上的资料,如今结合着本身的理解,给你们分享一下我本身对JS做用域的理解。前端
这里有三个重要的概念:执行环境、做用域、变量对象函数
(JS高级程序设计解释)
执行环境 :定义变量或函数可访问的其余数据,来决定它们的行为。
变量对象 :保存执行环境中定义的变量和函数。
做用域链 :保证对环境中定义的变量和函数的有序访问。设计
通俗来讲,执行环境和做用域就是变量或函数有效执行所在的一个环境。
总结一下这三者的关系:每一个执行环境执行时都会产生一个做用域,做用域前端都有一个变量对象来保存环境中的变量和函数。code
知道这3个重要概念后,要想搞清做用域,就要先清楚JS程序的预解析过程:
JS程序开始执行时会先解析语法(检查错误等等)、解析内存,而后把function、var解析到变量对象里。
这里注意解析var变量时只是会把变量名称解析,而等到程序运行到变量赋值时才会向变量赋值。对象
var a="A"; function test(){ console.log(a);//undefined var a="B"; } test();
这段代码的第一个console.log之因此会是undefined,缘由是函数内部的a变量在预解析时已经被解析到变量对象里,但没被赋值。因此函数执行时找到函数里未被赋值的a变量,输出undefined。内存
搞清楚预解析后,在判断做用域范围:
由于做用域的查找顺序是由局部做用域一步步地往上找,直到找到声明的变量和函数或已经到了全局做用域。因此局部的做用域能够访问到外部做用域的变量,而外部做用域访问不到内部做用域的变量。作用域
var a="A"; function test(){ console.log(a);//“A” a="B"; } test(); console.log(a);//"B"
function test(){ b();//函数b会被预解析,所以能够调用,执行了输出1; var a=1; function b(){ console.log(1); console.log(a);//undefined var a=2; } } test();
以上例子参考网上资料。io
要想搞清做用域,首先要搞清预解析,而后判断做用域范围,先判断本层环境有无声明及赋值,若是有声明,则判断调用前是否赋值。若是找不到声明,则一层层往外部的做用域找,直到全局环境也找不到时,一般就会报错。console
若是有解释的不对或不清晰的,欢迎留言讨论。function