4

上一章我们讲了匿名函数和闭包,这次我们来谈谈闭包中作用域this的问题。

大家都知道,this对象是在运行时基于函数的执行环境绑定的,如果this在全局就是[object window],如果在对象内部就是指向这个对象,而闭包却是在运行时指向的window,因为闭包并不属于这个对象的属性和方法。
我们先来看一个例子关于全局作用域的问题:

var a = 'this is window';

var box = {
    a:'this is object',
    get:function () {
        return this.a;
    }
};
alert(this.a);        //返回window.因为是全局作用域

不难看出,这个时候,this的作用域是全局的。指向的是window.结合上句话来看例子,如果在对象内部就是指向的这个对象。

var a = 'this is window';

var box = {
    a:'this is object',
    get:function () {
        return this.a;
    }
};
alert(box.get());        //返回的是this is object 因为这个是box对象下的作用域

我们了解了作用域的问题。接下来我们就说说闭包中this对象作用域的问题:

var a = 'this is window';

var box = {
    a:'this is object',
    get:function () {
        return function () {    //闭包
            retun this.a;    
        };
    }
};
alert(box.get()());        //返回this is window.

这就奇怪了,明明嵌套了这么多层,怎么会指向window呢,这就是闭包的机制,还是刚刚那句话:闭包却是在运行时指向的window,因为闭包并不属于这个对象的属性和方法。

那我们如何讲闭包的作用域指针指向对象内部呢?
两种方法:1.使用call()对象冒充,2.将作用域赋值给变量

/*对象冒充*/

var a = 'this is window';

var box = {
    a:'this is object',
    get:function () {
        return function () {    //闭包
            retun this.a;    
        };
    }
};
alert(box.get().call(box));    //返回 this is object

使用call()传值box,将box对象冒充。从而使作用域指向box对象内部。

/*将作用域赋值给变量*/

var a = 'this is window';

var box = {
    a:'this is object',
    get:function () {
    /*这里的作用域是box,而不是window*/
     var scope = this;    //将作用域赋值给一个变量
        return function () {    //闭包
            retun scope.a;    
        };
    }
};
alert(box.get()());    //返回this is object.

IE浏览器中内存泄漏问题

大家都知道,闭包会使变量驻留在内存中,这也就导致了内存泄漏。但是只是针对IE浏览器,其他浏览器不会出现这种问题.

window.onload = function () {
    function box () {
    var div = document.getElementById('div');
    div.onclick = function () {
        alert(div.innerHTML);
    };
}
box();
};

这里的互相调用会导致IE浏览器内存泄漏,因为div.onclick引用了上面的var div,他俩互相引用导致内存泄漏,解决办法就是将用完的div赋值null,等待垃圾回收

window.onload = function () {
    function box () {
    var div = document.getElementById('div');
    var a = div.innerHTML;
    div.onclick = function () {
        alert(a);
    };
    a = null;    //赋值为null,等待垃圾回收
}
box();
};

如果没有解除引用,必须等待浏览器关闭的时候才能释放!!!

关于作用域及内存泄漏的文章就到这里,欢迎老司机指正错误!

                                                                                                                   Brian Lee

Brian_Lee
397 声望40 粉丝

人生为棋,我愿为卒,行动虽慢,可谁见我曾后退一步!