定义
闭包的定义是指有权访问另一个函数作用域中的变量的函数。
在JavaScript中,闭包是函数和函数被声明时的语法环境的组合,语法环境包括在闭包创建时可以使用的函数、作用域以及变量
工作原理
当一个函数定义在另一个函数内部时,就创建了一个闭包,内部函数保留对外部函数的变量和作用域的引用
当外部函数执行完成并返回时,闭包仍然保持对外部函数捕获的变量和作用域链的引用。
闭包允许内部函数的访问和操作其外部函数的变量,即使外部函数的执行已经完成
此外,闭包保持对它外部函数的变量和作用域链的引入,可以防止它们被垃圾回收
简单地说,闭包可以帮助我们读取函数内部的变量,使这些变量的值始终保持在内存中,防止在函数调用之后被垃圾回收
创建闭包
创建闭包的方式就是在一个函数内部创建另一个函数
function fn(){
var user = 'atguigu';
return function(){
return user;
}//通过匿名函数返回局部变量user
}
console.log(fn()());//atguigu 通过box()()来直接调用匿名函数返回值
var b = fn();
console.log(b());//atguigu 另一种调用匿名函数返回值
作用
-
模拟块级作用域(匿名自执行函数)
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);//报错,无法访问
由于外部无法访问自执行函数内的变量,因此在函数执行完后会立刻被销毁,在外部无法访问。从而可有效避免在多人开发时由于全局变量过多而造成的命名冲突问题。另外由于作用域链的机制,局部变量要比全局变量的访问速度更快,可以提升程序的运行速度!
-
对结果进行缓存
var fn = function(){
var sum = 0;
for(var i = 0; i < arguments.length; i++){
sum += arguments[i];
}
return sum;
}
console.log(fn(1,2));//3
以上函数接收一些number类型的参数,并返回这些参数之和。由于每次传递的参数相同,所以返回的结果是一样的。这样势必会造成了一种浪费,在此时咱们可以通过缓存机制来提高这个函数的性能。
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;
}
}
})
上面的示例将计算后的结果缓存到局部变量cache当中,在调用这个函数时,先在缓存中查找,如果找不到,则进行计算,然后将结果放到缓存中并返回,如果找到了,直接返回查找到的值。
闭包的缺点
- 由于闭包可以让函数的变量保存在内存中,滥用闭包很容易造成内存消耗过大,导致网页性能问题,
解决方法:在退出函数之前,将不再使用的局部变量全部删除
- 闭包可以让函数内部的值在函数外部修改
当你把父函数当作对象
object使用,把闭包当它的公用方法(PublicMethod),把内部变量当私有属性(privatevalue)时,小心使用,不要随便父函数内部变量的值