前言:看了很多闭包的博客,总结一下。也是对自己的一种锻炼和加深自己的理解。前端自学中,欢迎大家指点,谢谢~
一、函数表达式
定义函数表达式的方式有两种:一种是函数声明,一种是函数表达式
1.函数声明
function fun() {
//函数体
}
用函数声明去定义一个函数用关键字function,后面加函数名,用name属性可以得到函数名
alert(fun.name);//fun
函数声明最重要的特征是函数声明提升,通俗一点就是说可以把函数声明可以放在函数调用后面。
sayhi();
function sayhi() {
}
2.函数表达式
var sayhi = function() {
//函数主体
}
函数表达式的调用不能在函数表达式之前,必须在后面。
二、闭包
为什么在介绍闭包之前要写函数声明方式呢?那接下来我要讲的和这个有关系
首先讲一下声什么是闭包,《javascript高级编程设计》里面是这样定义的:闭包是指有权访问另一个函数作用域中的变量的函数。那按照这句话的意思就是闭包是一个函数咯,网上很多关于闭包的文章都提到闭包的本质是一个连接函数内部和外部的桥梁。所以闭包有两个作用:一是读取函数内部的变量。而是让这些变量一种保持在内存中。
先给出一个问题吧?
怎么去实现将数字0~9每过一秒依次弹出?
举个例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>闭包</title>
</head>
<body>
</body>
<script type="text/javascript">
function fun() {
for (var i = 0; i < 10; i++) {
(function(i){
setTimeout(function(){
alert(i);
},(i+1)*1000);
})(i);
}
}
fun();
</script>
</html>
运行上面的函数,得到的结果是每过一秒依次输出0,1,2,3,4,5,6,7,8,9
换一种写法,如下
for (var i = 0; i < 10; i++) {
setTimeout(function(){
alert(i);
},(i+1)*1000)
}
得到的结果是每过一秒依次输出10,10,10,10,10,10,10,10,10
为什么会这样?匿名函数里面的alert(i)可以读取到外部函数的i值,这就是闭包。两种写法都可以得到读取到i,但第一种可以得到每一次for循环的i值,第二张却不行呢?
这一点我认为和闭包没关系,但是我看过的很多关于闭包的文章都把这两点混为一谈,下面是我的一点理解
先说为什么第二种不行,setTimeout定时函数里面的回调函数function它只是声明函数了,但没有调用(这也是为什么开始讲函数声明和函数调用),所以每次for循环的时候,i都在变化,而function没有运行。只有在for循环运行完i = 10的时候,定时函数调用了这个匿名函数。所以输出都是10.
那第一种为什么可以?第一中在setTimeout函数外部用一个匿名函数,然后让它自执行,传入参数i,当for循环的时候,i传入匿名函数的时候会复制一份变量i,也就是i从0到9都复制保持在该匿名函数的作用域中,故定时函数里的匿名函数可以正确输出i。
最后,欢迎大家指正和讨论,祝大家技术进步,早日成为大神!