Js闭包函数是什么?
闭包是指有权访问另一个函数作用域中的变量的过程。我们称调用的这个函数是外部函数,其返回的函数是内部函数,但是问题来了,正常的情况下,一个函数调用结束时,其内部定义的变量会被销毁。但是如果说函数返回函数,这个被返回的函数中引用了其外部函数中定义的变量,那么这个时候这些变量是会以某种方式被保存起来供内部函数引用,这种情况下就会形成函数闭包
举个例子
要求:
有五个按钮,我们每点击某个按钮一次这个按钮可以记录点击的次数,每点击一次就+1
如何实现?
第一步,肯定先写结构样式了,当然css样式请君自行改进😂
/*html结构*/
<body>
<button>点击次数:0次</button>
<button>点击次数:0次</button>
<button>点击次数:0次</button>
<button>点击次数:0次</button>
<button>点击次数:0次</button>
</body>
未使用闭包实现
//获取所有的按钮
var btns = document.querySelectorAll("button");
// for循环遍历所有按钮
for (var i = 0; i < btns.length; i++) {
// 为每个按钮添加一个自定义属性index索引
btns[i].index = i;
//定义numclck记录点击次数
var numclck = 0;
// 点击事件
btns[i].onclick = function () {
numclck++;
// this.index 当前点击的这个按钮,通过索引index得到
btns[this.index].innerHTML = `点击次数:${numclck}次`;
}
}
我们发现可以实现我们要求的效果,当然这里我们也可以用ES6新增的关键字let来声明我们的变量i,我们来试一下
/*可以发现代码是不是少了很多,为什么呢?可已看下我发的let、const、var的区别那篇文章你就会明白*/
var btns = document.querySelectorAll("button");
for (let i = 0; i < btns.length; i++) {
let numclck = 0;
btns[i].onclick = function () {
numclck++;
btns[i].innerHTML = `点击次数:${numclck}次`;
}
}
使用闭包来实现
//获取所有的按钮元素
var btns = document.querySelectorAll("button");
for (var i = 0; i < btns.length; i++) {
//这里的i为自执行函数(Q2:是什么?)的形参 i为局部变量
(function(i){
var numclck = 0; //局部变量 因为这块内存空间没有被销毁,所以存在numclck和i的空间有5个,而且他们是独立的。
btns[i].onclick = function(){
numclck+=1;//也可以写为numclck++
btns[i].innerHTML = `点击次数:${numclck}次`;
}
})(i) //这里的i是for循环执行时的i,为全局变量,执行了5次
}
自执行函数是什么(FQ2)?
- 是一个在定义阶段就会立即执行的函数(也叫立即执行函数
IIFE)而且只会执行一次
/*语法 */
(function(){
//函数体
})();
总结
函数中嵌套函数,我们分别称他们为外部函数和内部函数,调用内部函数,内部函数可以使用外部函数的变量。这就是形成闭包函数的过程,使用闭包可以延长我们变量的使用寿命,在有些情况下非常适用。
var a = "小白";
function fn(){
var b = "老黑";
// 内部函数
function innerFn(){
var c = 666;
console.log(b); //在内部函数innerFn中并没有b但是这里我们可以用外部函数定义的b
}
return innerFn;
}
var res = fn(); //res指向innerFn
res();//调用res
console.log(a)