在将闭包之前我们首先需要重复说明一下作用域的问题。
在前面我们讲过,函数的内部可以使用函数外部的变量,而函数外部不能使用函数内部的变量。
因为函数内部的变量是局部变量,而函数外部的变量为全局变量。
那么,如果我们就是想在函数外部使用函数内部的变量怎么办呢?
这有两种解决办法:
一、闭包函数
二、回调函数
何为闭包函数
在函数内部返回一个函数,返回的这个函数就称为闭包函数。
由于函数内部的函数的作用域为函数内部,又由于变量的作用域始终是变量定义的位置,所以,当我们返回内部函数时,连同函数内部的作用域也一同返回了。
这样一来闭包函数就获得了函数内部的作用域,当然就可以使用内部的变量了。
在讲闭包函数之前,我们还是再来回忆一下变量的作用域
请看以下代码
<!DOCTYPE html>
<html>
<head>
<title>变量的作用域始终是变量定位的位置</title>
<script src="./jquery.js"></script>
</head>
<body>
<script type="text/javascript">
var num = 100;
var f = function () {
console.log(num);
};
function f1() {
var num = 200;
f();
}
f1();
</script>
</body>
</html>
在以上代码中,我们在函数的外部定义了一个num变量并赋值为100,在f1函数的内部又定义了一个num变量并赋值为200.
然后在f1函数内部调用f函数,然后在外部调用f1函数。
大家可以想一下,输出结果是什么?
不错,是100,因为f函数内部没有定义num变量,所以它顺着作用域链向上找,找到了num=100。
再看下面的例子
<!DOCTYPE html>
<html>
<head>
<title>变量的作用域始终是变量定位的位置</title>
<script src="./jquery.js"></script>
</head>
<body>
<script type="text/javascript">
var num = 100;
var f = function(){
console.log(num);
};
function f1(){
var num = 200;
return f;
}
var res = f1(); // res 就是 f函数
res();
</script>
</body>
</html>
在上面的代码中,我们分别定义了f和f1两个函数,在f1中定义了一个num变量并赋值为200,然后将f函数返回,由res变量接收,那么res()就等于f(),那么请问输出的结果什么?
没错,还是100,因为变量的作用域始终在变量定义的位置,与调用位置毫无关系。
为什么不停的说这一点呢,因为在编程过程中常常会搞不清楚某个变量到底指向的谁。
通过上面的实验我们似乎明白了点什么,如果我们想要获得函数内部的作用域,即:想要在函数外部使用函数内部的变量,是不是把函数定义到内部,然后再把函数返回给外部就可以了呢?是的,这就叫做闭包。
请看下面的代码:
<!DOCTYPE html>
<html>
<head>
<title>变量的作用域始终是变量定位的位置</title>
<script src="./jquery.js"></script>
</head>
<body>
<script type="text/javascript">
var num = 200;
function f1() {
var num = 100;
function f2() {
console.log(num);
}
return f2;
}
var res = f1();
res(); //相当于在f1函数外面调用了f2函数,使用到了f1函数内部的变量,这种方式就是写了一个闭包
</script>
</body>
</html>
输出结果为100,它真的使用了函数内部的变量,有木有?
以上就是闭包函数的原理。
之所以这样用,是因为我们常常为了防止命名冲突,会将代码写到一个匿名函数中,然而我们又想在匿名函数外部使用匿名函数内部的变量,闭包函数它解决的就是这种函数外部使用函数内部变量的问题。
再次重复:匿名函数中返回的那个函数叫做闭包函数,这个匿名函数叫做闭包。
|