js做用域理解

学习笔记:(图中水印来自同名微信订阅号,现已更名为‘码上猿梦’)javascript

//javaScript做用域:html

    //首先声明一点,js中没有块级做用域,java

        好比java中for循环中for(int i = 0; i < arr.length; i++){}中的变量i只能在for循环的大括号内部能访问,c#

     //可是在js中,for(var i = 0; i < arr.length; i++){},i的做用域是包含了这个for循环的函数的做用域,或者是全局做用域.微信

 

1.全局做用域函数

(1).最外层函数和定义在最外层函数外面的变量具备全局做用域:性能

        (2).没有使用var关键字声明变量学习

上面的代码等价于下面的代码:(没有使用var关键字声明的a自动变为全局变量)测试

//2.局部做用域this

//与全局做用域相反,局部做用域就是声明定义在函数内部的变量或者函数,他们拥有局部做用域,也叫函数做用域,

//这些变量也叫局部变量,这些变量只能在声明定义他们的函数里面访问,

 

        //做用域链:以前学过java, 目前在自学c#和javaScript, 学js才发如今js中真的是万物皆对象: 在普通代码中表现的比在java和c#中更加完全. C#中的委托将函数名做为对象当成参数传递, java中也有这样的 , 那就反射. js中全部的东西都是对象, 函数也是对象, 它具备属性和方法, ( 在java中函数也能够说是方法, 但在js中这样说函数比较恰当,由于函数也是具备方法的. )

        //函数和其余对象同样, 拥有能够经过代码访问的属性和一系列仅供js引擎访问的内部属性, 其中有一个内部属性就是做用域链 [[scope]] , 这个内部属性包含了函数被建立时函数做用域中全部对象 ( 函数里面的函数也是对象 ) 的集合, 这个集合被称为函数的做用域链, 它决定了哪些数据可以被这个函数访问. 每一个函数都会有这样一个做用域链, 这样一来就会有不少个不一样做用域链,

[[scope]] 里面存放的只是一个地址, 也就是Scope chain的地址,[[scope]]指向了Scope chain,Scope chain是一个链表结构,里面存放着各类函数做用域,其中也包括全局做用域,

        //程序尚未执行的时候,这个链表的最顶端存放的是全局做用域,好比这段代码:

        当函数被建立的时候,它的做用域链就会填入一个全局对象,这个全局对象包含了全部的全局变量,(只列举了部分变量)

以下图:

//若是开始执行add函数,

var total = add(5, 10);

 

        //那么这个链表的最顶端必定是当前正在执行的函数的函数做用域(是函数做用域,不是做用域链),全局做用域天然在第二层了(其实在这里我在想,这里的链表是否是栈,这点我没有想明白,留一个疑问吧,之后再思考)

//补充一点:当执行流进入一个函数时,也就是一个函数要被执行时,会建立一个"运行时期上下文(execution context)"的执行环境,这也是一个内部对象, 这个运行时期上下文也是一个做用域链, 也是包含着该函数做用域中全部的对象, 运行时期上下文做用域链是由以前这个函数的做用域链初始化的, 而后js引擎又会去建立一个活动对象(Active Object),这个活动对象包含了函数运行期全部的局部变量,参数以及this等变量,

以下图:

 

        //这个活动对象用于标识符的解析,也就是当你要使用一个变量时,活动对象会去它的做用域链中的一个个函数做用域去遍历寻找该变量的标识符,若是找到了就使用这个标识符对应的变量,

若是没有找到,那就向下遍历另外一个函数做用域,直到找到为止,可是若是一直遍历到了全局做用域都没有找到和该标识符的定义,那就好吧,我给你报错.

(并且每一个标识符都要经历这个遍历寻找的过程,因此尽可能少使用全局变量,而应该多使用局部变量,有一个好的经验法则就是:若是一个跨做用域的对象被使用了一次以上,那就把它存储在局部做用域里再使用,这样也能减小代码量,但最重要的是提升了程序的性能.好比document这个全局变量,)

 

以上代码文字均手敲测试过,若有错误请指出,谢谢啦~~

欢迎关注同名微信订阅号:码上猿梦

笔记参考自梦想天空的博客,

博客地址:http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html

相关文章
相关标签/搜索