简介
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。摘自百度百科。
应用
有些时候我们往往会使用全局变量来作为计数容器,这是一个不好的习惯。原因如下:
我们可以使用闭包来代替使用全局变量,具体使用见下边:
比如我们需要实现一个打字机效果,第一次调用的时候正向播放文本,第二次调用的时候逆向播放文本。我们需要使用到一个标志位用于切换两种效果。
首先是实现正、逆切换,函数cut()
:
<script>
let myflag = true;//此时是一个全局变量
function cut() {
if (myflag) {
for (let i = 1; i <= str.length; i++) { //正放
setTimeout(function() { //定时器
word.innerHTML = str.substr(0, i);
}, (i - 1) * time);
}
} else {
for (let j = str.length; j >= 0; j--) { //倒放
setTimeout(function() { //定时器
word.innerHTML = str.substr(0, j);
}, (str.length - j) * time);
}
}
myflag = !myflag;
}
</script>
实现闭包:
我们将该函数封装在另一个函数play()
中,调用play就返回函数cut()
。
<script>
function play() {
let myflag = true;//此时是一个局部变量
function cut() {
if (myflag) {
for (let i = 1; i <= str.length; i++) { //正放
setTimeout(function() { //定时器
word.innerHTML = str.substr(0, i);
}, (i - 1) * time);
}
} else {
for (let j = str.length; j >= 0; j--) { //倒放
setTimeout(function() { //定时器
word.innerHTML = str.substr(0, j);
}, (str.length - j) * time);
}
}
myflag = !myflag;
}
return cut; //注意不要带上括号
}
</script>
案例
完善打字机案例
使用闭包完善一下案例:打字机效果(文本一个一个的显示,同时有光标闪烁效果)。
- 再将函数
play()
封装在一个函数show()
中。调用show()
函数会播放打字机动画,且返回动画所用时间。 - 函数
play()
后边添加调用(执行)play()
的部分,根据参数num设置播放次数。num:-1为正放一次,其他数字为正+逆。例如:-1,只正放一次。1,”正+逆“一次。2,”正+逆“两次。
let playFn = play(); //获取实现播放效果的函数
for (let i = 0; i < num; i++) {
setTimeout(function() {
playFn();
}, (str.length * time + timewait) * i);
}
函数show()
:
//封装好的函数
function show(word, str, num, time, timewait) { //num-1为正放一次,其他数字为正+逆。例如:-1,只正放一次。1,”正+逆“一次。2,”正+逆“两次。
//默认值
if (num == null) {
num = 1 * 2;
} else {
if (num == -1) { //只正放一次
num = 1;
} else {
num *= 2;
}
}
if (time == null) {
time = 200; //每个字符显示的时间
}
if (timewait == null) {
timewait = 2000; //正倒放等待时间
}
//播放(返回一个函数,调用返回的函数执行播放动作。多次调用,先正后逆。)
function play() {
let myflag = true;
function cut() {
if (myflag) {
for (let i = 1; i <= str.length; i++) { //正放
setTimeout(function() { //定时器
word.innerHTML = str.substr(0, i);
}, (i - 1) * time);
}
} else {
for (let j = str.length; j >= 0; j--) { //倒放
setTimeout(function() { //定时器
word.innerHTML = str.substr(0, j);
}, (str.length - j) * time);
}
}
myflag = !myflag;
}
return cut; //注意不要带上括号
}
let playFn = play(); //获取实现播放效果的函数
for (let i = 0; i < num; i++) {
setTimeout(function() {
playFn();
}, (str.length * time + timewait) * i);
}
return (str.length * time + timewait) * num;
}
播放多条文本
根据函数show()
返回的动画播放时间,使用嵌套的定时器即可实现播放多条文本的效果。
let word = document.querySelector('.word');//显示文本的容器
let str1 = "hello<br>world<br>!";//可以嵌入html代码
let str2 = "你好,我是轻率的保罗!";
let str3 = "很高兴见到你。";
let str4 = "测试:我只正放一次!";
let time_wait = 1000;//播放等待时间
setTimeout(function() {
time_wait = show(word, str1, 1); //播放第一句
setTimeout(function() { //第二句
time_wait = show(word, str2, 2);
setTimeout(function() { //第三句
time_wait = show(word, str3, 1);
setTimeout(function() { //第四句
show(word, str4, -1);//只正放一次
}, time_wait);
}, time_wait);
}, time_wait);
}, time_wait);
点击这里查看效果:传送门
打字机效果案例源码:https://cloud.189.cn/t/MbYraiArERrq(访问码:hzj6)
原文链接:js闭包