局部变量无法共享和长久的保存,而全局变量可能造成变量污染,所以我们希望有一种机制既可以长久的保存变量又不会造成全局污染。
每次定义一个函数,都会产生一个作用域链(scope chain)。当JavaScript寻找变量varible时(这个过程称为变量解析),总会优先在当前作用域链的第一个对象中查找属性varible ,如果找到,则直接使用这个属性;否则,继续查找下一个对象的是否存在这个属性;这个过程会持续直至找到这个属性或者最终未找到引发错误为止。
对于函数welcome(),定义welcome的时候会产生一个作用域链对象,为了表示方便,记作scopechain。scopechain是个有顺序的集合对象。
scopechain的第一个对象:为了方便表示记作sc1, sc1有若干属性,引用本函数的参数和局部变量,如sc1.hi ;
scopechain的第二个对象:为了方便表示记作sc2,sc2有若干属性,引用外层函数的参数和局部变量,如sc2.hello;
scopechain的最后一个对象:为了方便表示记作scn,scn引用的全局的执行对象,也就是window对象!,如scn.eval();
这里之所以可以弹出hello,world,原因就是变量解析时在welcome函数作用域链的第一个对象上找不到hello属性,然后就去第二个对象上找去了(结果还真找到了)。
所以,JavaScript中的所谓的高大上的闭包其实很简单,根本上还是变量解析。而之所以可以实现,还是因为变量解析会在作用域链中依次寻找对应属性的导致的。
闭包就是一个函数引用另外一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗!另外使用闭包也要注意变量的值是否符合你的要求,因为他就像一个静态私有变量一样。闭包通常会跟很多东西混搭起来,接触多了才能加深理解,这里只是开个头说说基础性的东西。
第一,对象的引用,函数也是对象,首先我们要理解js面向对象的思想和原型及引用,a和b是两个对象,b继承了a的原型,如果查询b.x这个属性,可是对象b中没有x这个属性,js就会顺着去a中找x这个属性,这也就是闭包中内部函数访问外部变量的原理。
第二就是js的垃圾回收机制,js的垃圾回收机制很简单,就是当一个变量的生命周期结束就是不用了的时候就会回收,举个例子,如果函数a中嵌套了函数b,a中声明了变量x,函数b访问函数a中的x,因为js中函数是级联执行的,也就是我们说的链式执行,a执行时x进入执行状态,如果不用了的话x就会进入执行完毕状态,这时就会被回收,如果这时候b引用了x变量,相当于x一直处于执行状态,垃圾回收机制就不会回收x,x变量会一直存在内存中,这种方式主要是为了私有变量而且可以存储那些不持久型的动态变量。
第三,就是作用域scope,在js中每一个函数都是广义的一个闭包,每个函数除了声明的全局变量剩下的变量都是自己的私有变量,作用域都只限于本函数作用域内,闭包相当于与外的一个接口,可以把私有变量给调用者使用。
网友评论 ()条 查看