跳转到内容

惰性函数

在非常多的场景中,都需要根据环境的不同,动态的改变函数的行为。

这里以复制函数举例,这是一个非常常见的场景。有些浏览器支持 navigator.clipboard.writeText,但是有些浏览器不支持,需要降级使用 document.execCommand("copy")

js
function copyText(text) {
	if (navigator.clipboard) {
		navigator.clipboard.writeText(text);
	} else {
		const textArea = document.createElement('textarea');
		textArea.value = text;
		document.body.appendChild(textArea);
		textArea.select();
		document.execCommand('copy');
		document.body.removeChild(textArea);
	}
}

但是浏览器支不支持是不是在一开始就可以确定下来了,因此我们可以将函数改进一下,在第一次时就确定下来函数使用那些 API 来完成功能。

js
function copyText(text) {
	if (navigator.clipboard) {
		copyText = (text) => {
			navigator.clipboard.writeText(text);
		};
	} else {
		copyText = (text) => {
			const textArea = document.createElement('textarea');
			textArea.value = text;
			document.body.appendChild(textArea);
			textArea.select();
			document.execCommand('copy');
			document.body.removeChild(textArea);
		};
	}

	copyText(text); // 第一次也要实现功能所以这里调用一下
}

在此之上呢,我们还可以将函数进行进一步的改进,将复制函数使用一个函数来的返回。将来如果需要修改复制函数的行为,再次调用 createCopyText 覆盖掉之前的。

这里说一个场景,在一些文档网站上需要限制用户的复制,就需要登录啊或者要会员啥的,那就可以在 createCopyText 中封装不同场景的逻辑,那在场景切换后(比如登录了、冲了会员啥的),那就可以重新调用 createCopyText 覆盖掉之前的。

js
function createCopyText() {
	if (navigator.clipboard) {
		return (text) => {
			navigator.clipboard.writeText(text);
		};
	} else {
		return (text) => {
			const textArea = document.createElement('textarea');
			textArea.value = text;
			document.body.appendChild(textArea);
			textArea.select();
			document.execCommand('copy');
			document.body.removeChild(textArea);
		};
	}
}

// 在开始就确定的使用的 API
const copyText = createCopyText();

或者封装成一个立即执行函数,这样就省去了第一次调用函数的麻烦。

js
const copyText = (function () {
	if (navigator.clipboard) {
		return (text) => {
			navigator.clipboard.writeText(text);
		};
	} else {
		return (text) => {
			const textArea = document.createElement('textarea');
			textArea.value = text;
			document.body.appendChild(textArea);
			textArea.select();
			document.execCommand('copy');
			document.body.removeChild(textArea);
		};
	}
})();

参考: