<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试</title>
<script type="text/javascript">
/****
* 首先说明:本例子旨在说明闭包的概念
* 如果只是为了获取点击哪一行li,方法很多,比如给其对象加索引等等
* lis[i] = i;下面就可以使用啦
*
* 闭包的标准概念(泛一点的概念是函数处处是闭包):
* 将一个函数嵌套在另一个函数内部.被嵌套的函数 (内部函数)是只属于嵌套它的函数(外部函数)的私有函数.
这样就形成了一个闭包.
下面的英文是MDN上面摘抄的
B forms a closure including A, i.e. B can access A's arguments and variables.
C forms a closure including B.
Because B's closure includes A, C's closure includes A,
C can access both B and A's arguments and variables.
In other words, C chains the scopes of B and A in that order.
**/
window.onload = function () {
var lis = document.getElementsByTagName("LI");
for (var i = 0, j = lis.length; i < j; i++) {
/*
其实一和二的写法没有什么区别,闭包的编码模式一般来说是这样的,
函数A内部定义啦一个函数B,函数B返回引用给其调用者A,并且赋值给其他作用域中的变量C
当C执行的时候,调用的是A返回的B的引用。这个时候即时A不存在啦,B依然可以获取到A定义的局部变量。
下面的2个变体当中无论是给自执行函数传递参数,函数在自执行函数里面定义一个变量获取外部的变量,
都是自执行函数所定义的局部变量,这里自执行函数就相当于A,返回的函数就相当于B,
lis[i].onclick就相当于C
*/
//方法一
// lis[i].onclick = function (arg) {
// return function () {
// alert(arg);
// };
// }(i);
//方法二
// lis[i].onclick = (function () {
// var row = i;
// /*
// var B = function(){
// alert(row);
// };
// return B;
// */
// return function () {
// alert(row);
// };
// })();
//方法3---这里涉及到的是Function的作用,直接创建的一个闭包。
/*
* Function 构造器创建一个新的Function 对象.
* 在JavaScript中每个函数(function)实际是一个Function对象.
* Function---函数构造器(A)的内部包含一个匿名的函数体(B) lis[i].conclick(C)
* */
// lis[i].onclick = Function('alert(' + i + ')');
//方法4---跟方法3差不多,方法3的构造器里面最后一个就是函数体返回给啦onclick
// 二方法四,只不过是执行构造函数里面的函数体,然后返回一个函数给onclick。
// 只要记住闭包的标准公司保管你不会错
lis[i].onclick = (Function("\nreturn(function() {\n\talert("+i+");\n});"))();
}
//from mdn--来自火狐开发者中心
// 下例演示了一个嵌套函数:就代指我们所说的标准定义的闭包模式
//addSquares---A square-----B a,b,c---C
function addSquares(a, b) {
function square(x) {
return x * x;
}
return square(a) + square(b);
}
a = addSquares(2, 3); // returns 13
b = addSquares(3, 4); // returns 25
c = addSquares(4, 5); // returns 41
/*由于内部函数形成了一个闭包, 你可以把这个内部函数当做返回值返回,
该函数引用到了外部函数和内部函数的两个参数 */
function outside(x) {
function inside(y) {
return x + y;
}
return inside;
}
fn_inside = outside(3);
result = fn_inside(5); // returns 8
result1 = outside(3)(5); // returns 8
/***
* 闭包内参数冲突,靠近优先原则(作用域链)
* @returns {Function}
*/
function outside() {
var x = 10;
function inside(x) {
return x;
}
return inside;
}
result = outside()(20); // returns 20 instead of 10
//再来一个闭包的例子,数字累加
/****
* 函数A(count)里面包含函数B(add),函数B返回引用给函数A,并且赋值给其他作用域作的局部变量C(myCount)
* @returns {Function}
*/
var count = function(){
var i=0;
var add = function(){
return i++;
}
return add;
};
var myCount = count();
myCount();//0
myCount();//1
}
</script>
<style type="text/css">
li {
height: 30px;
background: yellow;
}
</style>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</body>
</html>