1.闭包
闭包是指有权访问另外一个函数作用域中的变量的函数。
方法:在一个函数内部创建另一个函数。
用途:
1.设置私有的方法和变量;
2.匿名函数最大的用途是创建闭包,并且还可以构建命名空间,以减少全局变量的使用。从而使用闭包模块化代码,减少全局变量的污染。
3.对结果进行缓存。
var fn=(function(){
var cache={}//将结果缓存到该对象中
return function(){
var str=JSON.stringify(arguments);
if(cache[str]){//判断缓存中是否存在传递过来的参数,存在直接返回结果,无需计算
return cache[str];
}else{//进行计算并返回结果
var sum=0;
for(var i=0;i<arguments.length;i++){
sum+=arguments[i];
}
return cache[str]=sum;
}
}
})()
4.模拟块级作用域(匿名自执行函数)。
if(){}for(){}等没有作用域,所以在其块内声明的变量,在外部是可以使用的。
//javaScript没有块级作用域的概念
function fn(num){
for(var i=0;i<num;i++){}
console.log(i);//在for外部i不会失败
}
fn(2);
if(true){
var a=13;
}
console.log(a);//在if定义的变量在外部可以访问
通过匿名自执行函数可以模拟块级作用域
(function(){
//i在外部就不认识啦
for(var i=0;i<count;i++){}
})();
console.log(i);//报错,无法访问
缺点:
1.闭包会使得函数中的变量都被保存在内存中,滥用闭包可能会导致内存泄漏。解决办法:在函数退出之前,清除不使用的局部变量。
2.闭包会在父函数的外部改变父函数内部变量的值。
应用场景:
1.采用函数引用方式的setTimeout调用
setTimeout的第一个参数一般是一个即将要执行的函数(不能带参数,通过闭包可以实现传参效果),第二个参数是一个延迟时间。
function f1(a) {
function f2() {
console.log(a);
}
return f2;
}
var fun = f1(1);
setTimeout(fun,1000);//一秒之后打印出1
2.实现函数内的局部变量的累加
function fn(){
var num=100;
return function(){
num++;
return num;
}
}
var b=fn();//获得函数
//你会发现局部变量num并没有在内存当中消失
console.log(b());//调用匿名函数
console.log(b());//第二次调用匿名函数,实现累加
3.回调
4.封装私有变量
5.小范围代替全局变量
(function(){
var a = 1;
function fun1(){
console.log(a)
}
function fun2(){
console.log('测试:'+a)
}
fun1() //1
fun2() //测试:1
})()
console.log(a) //报错
6.访问私有变量(局部变量/函数的参数/函数内部定义的其他函数-闭包)的特权 ----- 有权访问私有变量和私有函数的公有方法
function Person(value){
var name = value;
this.getName = function(){
return name;
}
this.setName = function(value){
name = value
}
}
var person = new Person('John');
console.log(person.getName()); //John
person.setName('lucy')
console.log(person.getName()); //lucy
补充:
内存泄漏:程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。