使用闭包实现点击按钮切换 toggle

更新日期: 2022-07-01阅读: 958标签: 闭包

前言

我以往在实现点击按钮切换dom元素样式的时候,使用的是在全局范围内定义一个flag变量,然后用true和false来对应不同的状态。

const btn = document.querySelector('#btn');	//获取按钮元素
let flag = false;	//flag是全局变量

//事件监听绑定点击事件
btn.addEventListener('click',function(){
	if(flag){
		//状态1
	}else{
		//状态2
	}
	flag = !flag;	//切换状态(通过修改flag的值:true或false)
});

//...如果代码量很多的话,我们可能在其他地方不小心使用着同样叫做flag的变量

flag = doSomethingToFlag();	//其他代码可能对flag的值进行了(意料之外的)修改

这个flag变量其实本意上只是用在按钮的点击事件上,但是flag位于全局范围内,其他代码都可以对flag的值进行修改,从而可能导致意料之外的情况发生。因此,使用全局变量表示不同状态是不可取的做法。

最近在学习闭包的概念,尝试着使用闭包实现点击按钮切换不同状态。


分析

使用闭包我们可以把表示状态的flag变成私有变量。

const btn = document.querySelector('#btn');	//获取按钮元素

function click(){
	let flag = true;	//这里的flag不再是全局变量

	function closure(){
		if(flag){
			console.log('on');	//这里表示状态1
		}else{
			console.log('off');	//这里表示状态2
		}
		flag = !flag;	//切换状态
	}
	return closure;
}

btn.addEventListener('click',click());	//绑定点击事件

console.log(flag);	//报错:flag is not defined

我们在click()函数内部定义了closure()函数,当closure()函数被返回并在其他地方被使用后,它仍然引用着flag,这就导致了click()函数被销毁,但是flag不会被销毁,也就是形成了闭包。

这里稍微对代码做一些改进,使其复用性更高,也就是封装toggle()函数:

//toggle()函数接收一个按钮和两个函数:on()和off();
//其中on()表示第1种状态要执行的内容,off()表示第2种状态要执行的内容
function toggle(btn, on, off) {
	//使用闭包
	function click() {
		let flag = true;

		function closure() {
			if (flag) {
				on();//这里执行状态1要执行的内容
			} else {
				off();//这里执行状态2要执行的内容
			}
			flag = !flag;
		}

		return closure;
	}

	//为按钮绑定点击事件
	btn.addEventListener('click', click());
}

将功能封装好后,就可以很方便的将toggle事件绑定到按钮上:

const btn = document.querySelectorAll('.btn');	//获取若干个按钮

for (let i = 0; i < btn.length; i++) {//使用for循环为这些按钮都绑定toggle事件
	//toggle函数的三个参数分别是:按钮DOM元素、状态1要执行的内容、状态2要执行的内容
	toggle(btn[i],
	function on() {
		//doSomething:这里填入状态1要执行的代码
	},
	function off() {
		//doSomething:这里填入状态2要执行的代码
	});
}

经过测试可以发现,各个按钮对应的flag是独立的,互不干扰的。这是因为:

每一次绑定点击事件时,toggle()函数内部的click()函数占有一定内存空间,而函数调用后,内存被回收,flag由于闭包的特性被保留下来;

又因为每次调用click()函数开辟的是不同的内存空间,因此内部对应的flag也是不同的,故每一个按钮都能和一个flag一一对应,不会互相干扰。

链接: https://fly63.com/article/detial/11835

前端开发闭包理解,JavaScript-闭包

闭包(closure)是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠...

使用闭包的方式实现一个累加函数 addNum

使用闭包的方式实现一个累加函数 addNum,参数为 number 类型,每次返回的结果 = 上一次计算的值 + 传入的值

javascript中闭包最简单的介绍

JavaScript 变量可以是局部变量或全局变量。私有变量可以用到闭包。闭包就是将函数内部和函数外部连接起来的一座桥梁。函数的闭包使用场景:比如我们想要一个函数来执行计数功能。

js循环中的异步&&循环中的闭包

for循环中let 和var的区别,setTimeout(func,time)函数运行机制,一个需求,一个数组array[1,2,3,4,5],循环打印,间隔1秒

深入了解JavaScript的闭包机制

这篇文章主要介绍了JavaScript的闭包机制,针对内嵌函数的变量访问等问题分析了JS的闭包,写的十分的全面细致,具有一定的参考价值,JavaScript 变量可以是局部变量或全局变量。 私有变量可以用到闭包。

JavaScript 作用域、命名空间及闭包

变量作用域:一个变量的作用域是程序源代码中定义这个变量的区域,在函数内声明的变量是局部变量,它只在该函数及其嵌套作用域里可见(js 函数可嵌套定义);

Js中的闭包

闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式就是在一个函数内部创建另一个函数。来看下面的示例:

js闭包问题

使用闭包能够让局部变量模拟全局变量一样,但是它只能被特定函数使用。我们都知道:1.全局变量可能会造成命名冲突,使用闭包不用担心这个问题,因为它是私有化,加强了封装性,这样保护变量的安全

JS之闭包的定义及作用

在学习闭包之前,你必须清楚知道JS中变量的作用域。JS中变量的作用域无非就全局变量和局部变量,两者之间的关系是函数内部可以直接访问全局变量,但是函数外部是无法读取函数内部的局部变量的

Js函数高级-闭包

JavaScript的运行机制:(1)所有同步任务都在主线程上执行,形成一个执行栈。(2)主线程之外,还有一个“任务队列”,只要异步任务有了运行结果,就在“任务队列”之中放置一个事件。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!