在前端学习中,作用域这个问题一直被广泛提起,什么是作用域,什么又是作用域链?在Javascript中,怎么去理解这些概念都是学好这门语言的关键,所以在学习前端开发的过程中,我需要也很有必要去学习和总结下javascript----作用域。
作用域并不难,但是去很少有人能稍微深入的解释什么是作用域,知其然而不知其所以然显然是远远不够的,所以我们就深入浅出一下,
本片博文旨在深度去分析作用域,如有总结不到位之处,请读者海涵并在评论区指出。
谈到作用域就不得不谈到一个名词----执行环境。什么叫执行环境呢?
执行环境是Javascript中最为重要的一个概念,它定义了变量或函数有权访问其他数据,决定了他们各自的行为。那么在每个执行环境中都有一个叫做“变量对象”的object,执行环境中的所有变量和函数都保存在这个对象中,这个object是无法被访问到了,它只能在后台被javascript解释器访问到。
浏览器在解析Javascript代码的时候会为每个函数创建一个执行环境,并在该执行环境中生成一个变量对象来存储变量和其内部的函数。我们常常用到的window就是最外围的执行环境,也叫全局执行环境,每个执行环境的代码执行完成之后,该环境被销毁,其中的变量对象也将被销毁,而全局执行环境只会在浏览器或网页关闭的时候被销毁,其他的执行环境(或者内部的)则为局部执行环境(函数)。
每个函数都有自己的执行环境,那么当代码的执行流进入到一个函数时,会将该执行环境推入到一个环境栈中,在函数执行完成之后又将其弹出,把对这个执行环境的控制权交还给之前的执行环境,当代码在一个执行环境中执行的时候,会将该环境中的变量对象连入到作用域链中。作用域链的作用就是保证对执行环境中的有权访问的变量和函数有序的访问。说到这里,大家可能有些迷糊啦,那么就用点代码和图片来解释下吧。
- //window scope
- var name0 = 'scope0'<p>console.log(name0) //这里可以访问到name0
- function scope1(){<p>
- var name1 = 'scope1'<p> console.log(name0,name1) //这里可以访问到name0,name1
- function scope2(){
- var name2 = 'scope2'<p> console.log(name0,name1,name2) //这里可以访问到name0,name1,name2
- function scope3(){
- var name3 = 'scope3'<p> console.log(name0,name1,name2,name3) //这里可以访问到name0,name1,name2,name3
- }
- }
- }
当JS解释器去执行这段代码的时候,会生成4个执行环境,分别是window,scope1,scope2,scope3。然后再执行JS代码的时候,会把每个执行环境推入到执行栈中,并生成变量对象给连接到作用域链中(从上到下),***生成的作用域链就为:
window→scope1→scope2→scope3
对于每个执行环境中的变量对象来说,它的作用域链就是它本生加上它之前的变量对象(例如scope2的作用域链就是scope2和它之前的 scope1和window)。我们先前说道,每个执行环境中的变量对象就是该执行环境能够访问到了变量和函数,个人理解为这个函数就是变量对象的作用域 链上其他的变量对象,那么就很好理解了,我们分析下上面代码scope2的变量对象上有哪些东西,首先是参数数组(arguments,这里为[])还有 name2变量,然后是scope1的变量对象和全局变量对象。
说了这么多,提了那么多概念和名词,我们好像只是说到了作用域链,但是并没有说到作用域,这不是扯淡嘛!!!!好吧,我们现在就来谈谈作用域。
还是先来扯下概念吧。是每个执行环境可以通过作用域链向上访问这个他的作用域链的其他执行环境,但是不能向下访问。这个就是作用域啦。。。
还是拿scope2函数来说吧,他可以访问name2,name1,name0但是不能访问name3,这个就是作用域的限定,他只能访问到 scope1和window的执行环境(还有它本身)。额,就这么一小段,我自己都醉了,但是个人觉得作用域就这点东西,关键的是在与对执行环境、变量对 象和作用域链的理解。这些才是扎实的理解Javascript作用域的关键。
其实说到这里我感觉已经差不多了,***次写那么长的博文,文章水准还有待提高,这篇文章主要是我在看《javascript高级程序设计》的看 到作用域这小节,感觉作者写了太好了,于是乎加上了一些个人的理解就写了这篇博客。非常希望有对WEB开发有深刻理解的大大们提出批评和见解。