js闭包 单例模式的应用 以及代码优化

在这里插入图片描述

需求: 实现一个登录的弹框

方案1
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>单例模式</title>
</head>
<body>
	<button id="btn">Login</button>
	<script>
		var loginLayer = (function () {
			var div = document.createElement('div')
			div.innerHTML = 'Login Comp'
			div.style.display = 'none'
			document.body.appendChild(div)
			return div
		})()

		document.getElementById('btn').onclick = function () {
			loginLayer.style.display = 'block'
		}
	</script>
</body>
</html>
缺点: 加载完成时候已经创建好弹框 只是隐藏起来了,造成资源的浪费
方案2

改造一下上面的方案1的代码,不使用立即执行函数了
每次只有点击按钮以后,才调用createLoginLayer方法,创建一个div

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>单例模式2</title>
</head>
<body>
	<button id="btn">Login</button>
	<script>
		var createLoginLayer = function () {
			var div = document.createElement('div')
			div.innerHTML = 'Login Comp'
			div.style.display = 'none'
			document.body.appendChild(div)
			return div
		}

		document.getElementById('btn').onclick = function () {
			var loginLayer = createLoginLayer()
			loginLayer.style.display = 'block'
		}
	</script>
</body>
</html>

缺点:频繁创建销毁,占用资源
在这里插入图片描述

方案1和方案2都有缺点,怎么解决这个问题?就要引出单例模式的概念了:
在这里插入图片描述

简单来说,就是每次创建一个实例对象的时候,判断内存中是否已经有这个单例,有的话就返回,没有的话就创建,这就需要在内存中有一个标记,来标记是否存在这样的一个单例对象,所以我们想到了闭包

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>单例模式3</title>
</head>
<body>
	<button id="btn">Login</button>
	<script>
		var createLoginLayer = (function () {
			var div
			return function () {
				if (!div) {
					div = document.createElement('div')
					div.innerHTML = 'Login Component'
					div.style.display = 'none'
					document.body.appendChild(div)
				}
				return div
			}
		})()

		document.getElementById('btn').onclick = function () {
			var loginLayer = createLoginLayer()
			loginLayer.style.display = 'block'
		}
	</script>
</body>
</html>

在这里插入图片描述
内部的函数被保存到外部loginLayer,这样在外部loginLayer这里也能访问到函数createLoginLayer里面的变量div,于是产生了闭包。

效果如下:
在这里插入图片描述

代码到这里还可以优化:

写代码有一种思想,单一职责思想,我们用这个思想优化上述代码:
上述代码把形成单例和创建登录模块杂糅在一起了,我们这里用``单一职责```思想使这两个功能解耦
1.单例的职责:

var getSingle = function (fn) {
	var result
	return function () {
		return result || (result = fn.apply(this, arguments))
	}
}

2.创建登录模块职责

var createLogin = function () {
	var div = document.createElement('div')
	div.innerHTML = 'My-Login-Component'
	div.style.display = 'none'
	document.body.appendChild(div)
	return div
}

结合到一起:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>单例模式4</title>
</head>
<body>
	<button id="btn">Login</button>
	<script>
		// 1.单例职责(形成闭包)
		var getSingle = function (fn) {
			var result
			return function () {
				return result || (result = fn.apply(this, arguments))
			}
		}
		// 2.创建登录模块职责
		var createLogin = function () {
			var div = document.createElement('div')
			div.innerHTML = 'My-Login-Component'
			div.style.display = 'none'
			document.body.appendChild(div)
			return div
		}

		var createSingleLogin = getSingle(createLogin)

		document.getElementById('btn').onclick = function () {
			var loginLayer = createSingleLogin()
			loginLayer.style.display = 'block'
		}
	</script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值