惰性函数(函数重写)
惰性函数的定义
- 惰性函数表示函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了。
- 惰性函数的本质就是函数重写,所谓惰性载入,指函数执行的分支只会发生一次。
下面用在不同浏览器复制文本的案例为例,看看使用惰性函数和没有使用惰性函数的区别。
没有使用惰性函数的写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button onclick='copyText()'>复制文本</button>
<input type="text">
</body>
<script>
const inputText = document.querySelector('input')
function copyText(){
// 没有使用惰性函数,每次复制文本都会做一次判断
if(navigator.clipboard){
// 如果浏览器有clipboard API则直接在剪贴板中写入
navigator.clipboard.writeText(inputText.value)
}
else{
// 如果浏览器没有clipboard API(如IE浏览器)
// 则创建一个input标签并复制相应文本后再销毁创建的input标签(等价于if判断的复制文本效果)
inputText.setAttribute('value', inputText.value);
document.body.appendChild(inputText)
input.select()
document.execCommand('copy')
document.body.removeChild(input)
}
}
</script>
</html>
使用惰性函数的一般写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button onclick='copyText()'>复制文本</button>
<input type="text">
</body>
<script>
const inputText = document.querySelector('input')
function copyText(){
// 没有使用惰性函数,每次复制文本都会做一次判断
if(navigator.clipboard){
// 直接重写copyText函数
copyText = () => {
// 如果浏览器有clipboard API则直接在剪贴板中写入
navigator.clipboard.writeText(inputText.value)
}
// 第二次复制文本后copyText函数已被重写
copyText()
}
else{
// 直接重写copyText函数
copyText = () => {
// 如果浏览器没有clipboard API(如IE浏览器)
// 则创建一个input标签并复制相应文本后再销毁创建的input标签(等价于if判断的复制文本效果)
inputText.setAttribute('value', inputText.value);
document.body.appendChild(inputText)
input.select()
document.execCommand('copy')
document.body.removeChild(input)
}
// 第二次复制文本后copyText函数已被重写
copyText()
}
}
</script>
</html>
惰性函数的高阶函数写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button onclick="copyText()">复制文本</button>
<input type="text" />
</body>
<script>
const inputText = document.querySelector('input')
function createCopyText() {
if (navigator.clipboard) {
// 直接返回原本的copyText函数体
return () => {
navigator.clipboard.writeText(inputText.value)
}
} else {
// 直接返回原本的copyText函数体
return () => {
inputText.setAttribute('value', inputText.value)
document.body.appendChild(inputText)
input.select()
document.execCommand('copy')
document.body.removeChild(input)
}
}
}
// 有需要的时候就调用createCopyText函数,可以重复使用
// 相当于封装了copyText函数
const copyText = createCopyText()
</script>
</html>