概念
在一个函数中嵌套另一个函数,嵌套(内部)函数对其容器(外部)函数是私有的。闭包是一个可以自己拥有独立的环境与变量的表达式(通常是函数,因为ES6有块级作用域的概念)
闭包是指有权访问另一个函数作用域中变量的函数。
闭包作用:
- 可以在函数外部访问到函数内部的局部变量;
- 让这些变量始终保存在内存中,不会随着函数的结束而自动销毁;
// 案例
console.log('closure')
function add(){
var count = 0;
return function(){
count += 1;
return count;
}
}
var a = add();
function fun(){
alert(a());
}
fun();
fun();
// 定义了add()函数,函数内定义了count,返回值也是一个函数,内部函数引用外部函数变量count,因此形成闭包
闭包经典案例:要求点击每个li标签,弹出对应的索引。(0,1,2,3)
<ul>
<li>i</li>
<li>i</li>
<li>i</li>
<li>i</li>
</ul>
// 错误答案
for (var i = 0; i < elements.length; i++) {
elements[i].onclick = function () {
return (function (n) {
console.log(n);
alert(n);
})(i);
};
}
// 下面时这个题目的答案
// 每个li标签的onclick事件执行时,本身onclick绑定的function的作用域中没有变量i,i为undefined,则解析引擎会寻找父级作用域,
// 发现父级作用域中有i,且for循环绑定事件结束后,i已经赋值为4,所以每个li标签的onclick事件执行时,alert的都是父作用域中的i,也就是4。
// 这是作用域的问题。这里onclick事件绑定的函数形成闭包,但引用的变量i是全局的。闭包真正的含义是,如果一个函数访问了此函数的父级及父级以上的作用域变量,就可以称这个函数是一个闭包。
// 将for循环的var改为let就可以实现想要的效果
// 正确答案
for (let i = 0; i < elements.length; i++) {
elements[i].onclick = function () {
return (function (n) {
console.log(n);
alert(n);
})(i);
};
}
闭包造成内存泄漏问题
// 借助以下实例进行讲解
function fn () {
let count = 1
function fun () {
count ++
console.log(`函数内部调用${count}次`)
}
return fun
}
const result = fn();
result() //2
result() //3
// 1、result是一个全局变量,代码执行完毕不会立即销毁
// 2、result可以找到fn()函数,fn()函数return fun(),因此 fun()也不会销毁。
// 3、fun()引用到了父级作用域的count,因此,在引用的count便不会被垃圾回收机制回收。
// 此时,闭包就引起了内存泄漏问题
// 正常情况下,一般的局部变量函数执行完就会销毁,但是我们这里的result没有销毁,所以它引用到的count也会留存在内存当中。
闭包的应用
函数工厂
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
模拟私有方法
var makeCounter = function () {
var privteCounter = 0;
function changeBy(val) {
privteCounter += val;
}
return {
increment: function () {
changeBy(1);
},
decrement: function () {
changeBy(-1);
},
value: function () {
return privteCounter;
},
};
};
var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */
标签:闭包,function,console,函数,count,JS,理解,return
From: https://www.cnblogs.com/fishlittle/p/17355108.html