闭包的定义
闭包(closure)指的是引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的,它是作用域的一种特殊应用。
触发闭包的情况
-
函数当作参数被传递。
-
函数当作返回值被返回。
-
立即调用的函数表达式。
eg:
<!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>
</body>
<script>
// 函数当作参数被传递
function fn(cb) {
const a = 100;
cb();
}
const a = 500;
fn(function () {
console.log(a);// 500
});
// 函数当作返回值被返回
function fn() {
const a = 1;
return function () {
console.log(a);// 1
};
}
const a = 5;
const cb = fn();
cb();
// 立即调用的函数表达式
(function (index) {
console.log(index);// 10
})(10);
</script>
</html>
闭包的应用
- 隐藏变量。
eg:
<!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>
</body>
<script>
// 隐藏了data这个变量,它只能在fn中使用
function fn() {
const data = {};
return {
set: function (key, val) {
data[key] = val;
},
get: function (val) {
return data[val];
}
};
}
const json = fn();
json.set("age", 18);
console.log(json.get("age"));
</script>
</html>
- 解决用来计数的循环变量泄露为全局变量的问题。
eg:
<!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>0</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
</body>
<script>
const aBtns = document.getElementsByTagName("button");
for (var i = 0; i < aBtns.length; i++) {
// aBtns[i].onclick = function () {
// console.log(i);
// }
(function (index) {
aBtns[i].onclick = function () {
console.log(index);
}
})(i);
}
</script>
</html>
拓展:
自由变量:不在自己作用域内的变量就是自由变量。
想知道自由变量的值是多少要去函数定义的外层作用域中去查找,与函数调用的位置无关,只与函数定义的位置有关。
eg:<!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> </body> <script> const a = 100; function fn() { console.log(a); // 自由变量 } </script> </html>