一 . 什么是闭包?概念?
官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。(函数就是一个表达式)
JavaScript中所有的function都是一个闭包。不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的“闭包”。
我们之前常说的一些什么保持变量内部私有性,避免了全局变量因为命名冲突造成的全局污染;支持跨作用域访问延伸变量作用范围,其实我们细想一下这些都是函数的作用范围
闭包的特点:
- 让外部访问函数内部变量成为可能;
- 局部变量会常驻在内存中;
- 可以避免使用全局变量,防止全局变量污染;
- 会造成内存泄漏(有一块内存空间被长期占用不被释放,参数和变量不参与垃圾回收机制
二、闭包的创建
在JavaScript中万事万物都是对象,那么函数也是个对象,则匿名函数也是个对象。
函数的返回值可以是任意类型,那么也可以是一个对象。
例子1
function funA(){
var a = 10; // 在外部函数定义一个参数;
return function(){ //闭包函数;
console.log(a); //在子函数内部访问这个变量
}
}
funA();
这就是一个最基础的闭包,可以访问其所在的外部函数中声明的参数和变量(但是我们这里是练习的时候需要注意,要用var去声明变量不能使用let,这里就牵扯到了他们之间的区别作用域等)
例子2
function outerFn(){
var i = 0;
function innerFn(){
i++;
console.log(i);
}
return innerFn;
}
//每次外部函数执行的时候,都会开辟一块内存空间,外部函数的地址不同,都会重新创建一个新的地址
//开辟新空间1
var inner = outerFn();
inner();
inner();
inner();
//输出 1 2 3
//开辟新空间2
var inner2 = outerFn();
inner2();
inner2();
inner2();
//输出 1 2 3
每次外部函数执行的时候,外部函数的引用地址不同,都会重新创建一个新的地址
例子3
function fun(){
var a = 1;
return function(){
return ++a;
}
}
alert(fun()()); //2
alert(fun()()); //2
这是常见的返回闭包函数,每次引用都赋予了新的地址
例子4
function fun(){
var i = 0;
function fun(){
i++;
console.log(i);
}
return fun;
}
var numa = fun();
var numb= fun();
numa();//1
numb();//1
numa();//2
numb();//2
外部函数被返回(寿命终结)了之后,可以访问其所在的外部函数中声明的参数和变量
通过以上了解,那么究竟什么是闭包呢?
闭包是指在一个函数内部创建另一个函数,并且内部函数可以访问外部函数的变量和作用域。闭包在JavaScript中是一种强大的特性,具有以下优点和缺点:
优点:
-
数据私有性:闭包可以创建私有变量和函数,将其封装在函数内部,外部无法直接访问。这样可以有效地防止变量被外部篡改或污染全局命名空间。
-
保持状态:闭包可以捕获外部函数的变量,并将其保持在内存中,即使外部函数执行完毕后,闭包依然可以访问和修改这些变量。这使得闭包可以用于创建具有记忆能力的函数,保存状态信息。
-
实现数据封装:通过闭包,可以将数据和操作封装在一个函数内部,提供了更好的模块化和封装性,使代码更具可读性和维护性。
缺点:
-
内存消耗:闭包会导致变量长期驻留在内存中,不会被垃圾回收机制回收。如果闭包被滥用或存在循环引用,可能会导致内存泄漏的问题,影响性能和占用更多的内存。
-
性能损耗:由于闭包需要维护外部变量的引用,访问这些变量的速度较慢,会带来一定的性能损耗。尤其是在循环中创建闭包时,可能会导致大量的内存开销和性能问题。
-
安全性问题:闭包可以访问外部函数的变量,如果外部函数中包含敏感信息或者未经处理的用户输入,闭包的访问可能会导致安全性问题,例如信息泄露、注入攻击等。
因此,在使用闭包时需要权衡其优点和缺点。合理利用闭包可以提高代码的灵活性和可复用性,但过度使用或不当使用闭包可能会导致性能和安全问题。