javascript高级编程之函数表达式 递归和闭包函数(3)

this对象是在运行时基本函数的执行环境绑定的:在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象.不过,匿名函数的执行环境具有全局性,因此其this对象通常指向window.

var; var object={ name:"my object", getNameFunc:function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()());//the window(在非严格模式下)

每个函数在被调用时都会自动取得两个特殊变量:this和arguments.内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量.

不过,把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了.

var; var object={ name:"my object", getNameFunc:function(){ var that=this; return function(){ return that.name; }; } }; alert(object.getNameFunc()());//my object

在定义匿名函数之前,我们把this对象赋值给了一个名叫that的变量.而在定义了闭包之后,闭包也可以访问这个变量,因为它是我们在包含函数中特意声明的一个变量.即使在函数返回之后,that也仍然引用着object,所以调用object.getNameFunc()()就返回了my object.

注意:this和arguments也存在同样的问题.如果想访问作用域中的arguments对象,必须将对该对象的引用保存到另一个闭包能够访问的变量中.

var; var object={ name:"my object", getName:function(){ return this.name; } }; console.log(object.getName());//my object console.log((object.getName)());//my object console.log((object.getName=object.getName)());//the window

最后一行代码先执行了一条赋值语句,然后再调用赋值后的结果.因为这个赋值表达式的值是函数本身,所以this的值不能得到维持,结果就返回了"this window".

7.2.3 内存泄露

由于IE9之前的版本对JScript对象和COM对象使用不同的垃圾收集例程,因此闭包在IE的这些版本中会导致一些特殊的问题.具体来说,如果闭包的作用域链中保存着一个HTML元素,那么就意味着该元素将无法被销毁.

function assignHandlet(){ var element=document.getElementById("someElement"); element.onclick=function(){ alert(element.id); }; }

以上代码创建了一个作为element元素事件处理程序的闭包,而这个闭包则又创建了一个循环引用.由于匿名函数保存了一个对assignHandler()的活动对象的引用,因此应付导致无法减少element的引用数.只要匿名函数存在,element的引用数至少也是1,因此它所占用的内存就永远不会被回收.不过这个问题可以通过稍微改写一下代码来解决.

function assignHandlet(){ var element=document.getElementById("someElement"); var id=element.id; element.onclick=function(){ alert(id); }; element=null; }

上面代码中,通过把element.id的一个副本保存在一个变量中,并且在闭包中引用该变量消除了循环引用.

脚本之家友情提醒大家:闭包会引用包含函数的整个活动对象,而其中包含着element.即使闭包不直接引用element,包含函数的活动对象也仍然会保存一个引用.因此,有必要把element变量设置为null.这样就能够解除对DOM对象的引用,顺利地减少其引用数,确保正常回收其占用的内存.

下面给大家介绍下函数表达式。

在JavaScript 编程中,函数表达式是一种非常有用的技术。使用函数表达式可以无须对函数命名,从而实现动态编程。匿名函数,也称为拉姆达函数,是一种使用JavaScript 函数的强大方式。以下总结了函数表达式的特点。

函数表达式不同于函数声明。函数声明要求有名字,但函数表达式不需要。没有名字的函数表达式也叫做匿名函数。

在无法确定如何引用函数的情况下,递归函数就会变得比较复杂;递归函数应该始终使用arguments.callee 来递归地调用自身,不要使用函数名——函数名可能会发生变化。

当在函数内部定义了其他函数时,就创建了闭包。闭包有权访问包含函数内部的所有变量,原理
如下。

在后台执行环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域。通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。

但是,当函数返回了一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止。

使用闭包可以在JavaScript 中模仿块级作用域(JavaScript 本身没有块级作用域的概念),要点如下。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgzgzj.html