<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p id="help">Helpful notes will appear here</p>
<p>E-mail: <input type="text" id="email" name="email" /></p>
<p>Name: <input type="text" id="name" name="name" /></p>
<p>Age: <input type="text" id="age" name="age" /></p>
<script>
function showHelp(help) {
document.getElementById("help").innerHTML = help;
}
function callback(help) {
return function () {
showHelp(help)
}
}
function setupHelp() {
var helpText = [
{ id: "email", help: "Your e-mail address" },
{ id: "name", help: "Your full name" },
{ id: "age", help: "Your age (you must be over 16)" },
];
for (var i = 0; i < helpText.length; i++) {
/*
① 不可行:
var item = helpText[i];
document.getElementById(item.id).onfocus = function () {
showHelp(item.help)
}
因为变量 item 使用 var 进行声明,由于变量提升,所以具有函数作用域。当 onfocus 的回调执行时,item.help 的值被决定。
由于循环在事件触发之前早已执行完毕,变量对象 item(被三个闭包所共享)已经指向了 helpText 的最后一项。
*/
/*
② 可行 使用更多的闭包
var item = helpText[i];
document.getElementById(item.id).onfocus = callback(item.help)
所有的回调不再共享同一个环境, makeHelpCallback 函数为每一个回调创建一个新的词法环境。
在这些环境中,help 指向 helpText 数组中对应的字符串。
*/
/*
③ 可行 匿名闭包
(function () {
var item = helpText[i];
document.getElementById(item.id).onfocus = function () {
showHelp(item.help)
}
})() // 马上把当前循环项的 item 与事件回调相关联起来
*/
// ④ 可行 使用 const 而不是 var,因此每个闭包都绑定了块作用域的变量,这意味着不再需要额外的闭包
const item = helpText[i];
document.getElementById(item.id).onfocus = function () {
showHelp(item.help);
}
}
}
setupHelp();
</script>
</body>
</html>
闭包的使用
最新推荐文章于 2024-07-04 00:59:27 发布