1. 事件闭包的理解
闭包是指有权限访问另一个函数作用域中的变量的函数。 在 javascript 语言中,闭包就是函数和该函数作用域的组合。从这 个概念上来讲,在 js 中,所有函数都是闭包(函数都是对象并且函 数都有和他们相关联的作用域链 scope chain)。
官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的 环境的表达式(通常是一个函数),因而这些变量也是该表达式的一 部分。其实这 句话通俗的来说就是:JavaScript 中所有的 function 都是一个闭包。 不过一般来说,嵌套的 function 所产生的闭包更为强大,也是大部 分时候我们所谓的“闭包”。
2. 变量的作用域 要理解闭包,首先必须理解 Javascript 特殊的变量作用域。 变量的作用域无非就是两种:全局变量和局部变量。 Javascript 语言的特殊之处,就在于函数内部可以直接读取全局 变量。
案例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
// 闭包: 在js中任何一个函数都是一个闭包,但是嵌套的函数闭包作用会更大;
// 闭包: 一个函数中的变量 可以被其他函数所访问
//问题: 如何从外部读取函数内部的变量?
//解决: 在 函数体内嵌套函数
// function snake(){ //创建一个蛇对象
// var color='white'; //创建属性
// //var length=30;
// var width=20;
// var height=20;
// function snake1(){
var color_01='red';
// alert(color);
// }
// snake1();
// }
// snake(); //输出color的结果为: white
//以上函数嵌套 是 JS中特殊的作用域立链 scope chain
//父对象的所有变量,对子对象都是可见的,反之则不成立
function snake(){ //创建一个蛇对象
var color='white'; //创建属性
var width=20;
var height=20;
function snake1(){
return color;
}
// var color_01=snake1(); return color_01;
return snake1();
}
alert(snake());
</script>
</head>
<body>
</body>
</html>
练习案例1:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
// 创建一个学生 对象,具备属性 color, height,weight
function Student(){
var color='yellow';
var height=1.82;
var weight=60; //表示体重的属性
//第一种方法 不常用(不强大);
//return '肤色:'+color+'身高:'+height+'体重:'+weight;
//第二种方式: 通过在函数体内定义函数 返回,功能更加强大
function Student_01(){
return '肤色:'+color+'身高:'+height+'体中:'+weight;
}
return Student_01();
}
// 对于以上案例: Student_01() 就是一个闭包函数
/*闭包可以使用在许多地方.它的最大作用有两处:
一个是前面提到的可以读取函数内部的变量,
另一个就是让这些变量的值始终保持在内存中*/
</script>
</head>
<body>
</body>
</html>
案例2:
function outerFun(){
var a=0;
function innerFun(){
a++;
alert(a);
}
}
innerFun()
上面的代码是错误的.innerFun()的作用域在 outerFun()内部,所在 outerFun()外部调用它是错误的. 改成如下,也就是闭包:
function outerFun(){
var a=0;
function innerFun(){
a++;
alert(a);
}
return innerFun; //注意这里
}
var obj=outerFun();
obj(); //结果为 1
obj(); //结果为 2
var obj2=outerFun();
obj2(); //结果为 1
obj2(); //结果为 2
案例3:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
function outerFun() {
var a = 0;
alert(a);
}
var a = 4;
outerFun();
alert(a);
//结果是 0, 4.因为在函数内部使用了
//var 关键字 维护 a 的作用域在 outFun() 内部.
function outerFun() {
//没有 var
a = 0;
alert(a);
}
var a = 4;
outerFun();
alert(a);
//结果为 0, 0
//作用域链是描述一种路径的术语, 沿着该路径可以确定变量的值.当执行 a = 0 时,
//因为没有使用var关键字, 因此赋值操作会沿着作用域链到var a = 4;并改变其值.
</script>
</head>
<body>
</body>
</html>
案例4:
这段代码有两个特点: 1、函数 b 嵌套在函数 a 内部; 2、函数 a 返回函数 b。
这样在执行完 var c=a()后,变量 c 实际上是指向了函数 b,再执 行 c()后就会弹出一个窗口显示 i 的值(第一次为 1)。这段代码其实 就创建了一个闭包,为什么?因为函数 a 外的变量 c 引用了函数 a 内 的函数 b,
就是说: 当函数 a 的内部函数 b 被函数 a 外的一个变量引用的时候,就创建 了一个闭包。