什么是闭包,从事前端两年却没有去了解这些基础的知识,闭包对于学JavaScript的人来说是很重要的一个知识点,但是究竟什么是闭包呢?闭包是指有权访问另一个函数作用域中的变量的函数。常见的方法就是在一个函数内部创建另一个函数。
变量
变量按作用域分为两种,全局变量和局部变量,在函数中,全局变量可以直接被使用,但是在全局环境中,函数内部定义的局部变量却无法被直接使用。(注:在定义局部变量时一定要使用var,否则会将该变量定义成全局变量,不要因此而误会局部变量可以在全局使用)。
全局变量:
var a = 100;
function f1(){
console.log(a);
}
f1(); //100
局部变量:
function f1(){
var a = 200;
}
f1();
console.log(a); //出错,如果你先在浏览器上运行过上面全局变量的代码,那么结果会显示100。
函数中的全局变量:
function f1(){
a = 999;
}
f1();
console.log(a); //999,因为a已经是全局变量,所以在函数外可以直接获得
闭包
先看一下下面的代码:
function f1(){
var n = 1;
function f2(){
console.log(n);
}
return f2;
}
var result = f1();
result(); //1
函数f2中的代码就是闭包,闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成”定义在一个函数内部的函数”。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包的用途有两个,一个是前面的在另一个函数中调用函数变量,另一个作用是会使函数中的这些变量值始终保存在内存中,可以持续使用,这也是闭包的一个问题,就是太占用内存,也会导致内存泄漏。
function f1(){
var n = 999;
nAdd = function(){
n +=1;
};
function f2(){
console.log(n);
}
return f2;
}
var result = f1();
result(); //999
nAdd();
result(); //1000,从这里可以看出函数中的局部变量并没有因为函数调用结束后回收。
闭包中的this对象
在闭包中使用this对象可能会导致一些问题,this本身在运行时基于函数的执行环境,即作用域。在全局函数中,this指向widow,在函数被当做某个对象的方法调用时,this指向那个对象。不过,匿名函数的执行环境具有全局性,因此this会指向window。
var name = "The Window";
var object = {
name:"My Object",
getNameFunc:function(){
return function(){
return this.name;
};
}
};
console.log(object.getNameFunc()()); //The Window
所以我们在闭包中使用匿名函数时,我们需要在定义匿名函数前将this的对象赋给其他对象,然后在匿名函数中调用这个对象,就能避免这个问题。
var name = "The Window";
var object = {
name:"My Object",
getNameFunc:function(){
var that = this;
return function(){
return that.name;
};
}
};
console.log(object.getNameFunc()()); //My Object