一. 匿名函数
1. 函数的定义,可分为三种
1) 函数声明方式html
function
double(x) {
return 2*x;
}
2)Function构造函数,把参数列表和函数体都做为字符串,不方便,不建议使用安全
var
double =
new Function('x', 'return 2*x;');
3)函数表达式方式闭包
var
double = function(x) {
return 2*x;
}
该形式中,等号右边是一个匿名函数,建立函数完毕后,将该函数赋给了变量double。函数
2. 匿名函数
1)第一种方式this
var double= function(x) {
return 2*x;
}
等号右边是一个匿名函数。注意匿名函数不能直接独立的房子代码中,以下代码spa
functino(x) {
return 2*x;
}
//
SyntaxError: Unexpected token (
2)第二种方式code
(
function(x,y) {
console.log(x+y);
})(2,3);
建立一个匿名函数(在第一个括号内),第二个括号用于调用该匿名函数并传入参数。htm
二. 闭包(Closure)
闭包的含义:外层函数包含内层函数,内层函数能够访问外层函数的全部变量,即便外层函数执行完毕。(JavaScript做用域链)blog
题外话:上述对于闭包的解释与《JavaScript 闭包系列一》中不彻底吻合。 上述解释,闭包成立只需知足:函数inner嵌套在函数outer内部。另外一些文章对于闭包的解释,闭包成立须要两个条件:1)函数inner嵌套在函数outer内部;2)函数outer返回函数inner。对此,我已经凌乱了,各路大侠谁可以给个定论?token
Example 1:
函数outer是瞬间执行的(约0.00001毫秒),在函数outer体内建立了一个变量str,在outer执行完毕后,str变量未被释放,这是因为setTimeout内的匿名函数存在对变量str的引用。等到2秒后,匿名函数执行完毕,str才被释放。
function outer() {
var str = "closure";
setTimeout(
function() {
console.log(str);
}, 2000);
}
outer();
//
closure
Example 2:此例是否为闭包呢?
function outer() {
var i = 22;
(
function inner() {
console.log(i);
})();
}
outer();
//
22
Example 3:简化代码
function forTimeout(x, y) {
console.log(x + y);
}
function delay(x, y, time) {
setTimeout('forTimeout(' + x + ',' + y + ')', time);
}
//
简化后
function delay(x, y, time) {
setTimeout(
function() {
forTimeout(x,y);
}
,time);
}
delay(3, 4, 2000);
//
7
三. 匿名函数与闭包
匿名函数的最大用途是建立闭包,它也可用来构建命名空间,减小全局变量的使用。
Example1:
匿名函数中的addEvent和removeEvent为局部变量,可是能够经过全局变量oEvent使用它,大大减小了全局变量的使用,加强了网页的安全性。
var oEvent = {};
(
function() {
var addEvent =
function() {};
function removeEvent(){}
oEvent.addEvent = addEvent;
oEvent.removeEvent = removeEvent;
})();
Example2:
建立一个变量sun_mile_rain,并经过直接调用匿名函数初始化为5,这种小技巧有时十分有用。
var sun_mile_rain = (
function(x , y){
return x + y;
})(2 , 3);
console.log(sun_mile_rain);
//
5
//
也可以使用以下的方式,第一个括号只是帮助咱们阅读,可是不推荐下面这种书写格式
var sun_mile_rain =
function(x , y){
return x + y;
}(2 , 3);
Example3:
代码中,变量one定义在函数内部,是一个局部变量,所以外部是不能够访问的。但inner函数能够访问变量one,又将全局变量outer引用了inner,所以执行outer()能访问到one的值。
var outer =
null;
(
function() {
var one = 1;
function inner() {
one += 1;
console.log(one);
}
outer = inner;
})();
outer();
//
2
outer();
//
3
outer();
//
4
换一种形式:函数fn执行,返回inner,将fn的执行结果赋给全局变量outer。执行outer也能访问到one的值。所以可得知闭包的形式能够有多种。
function fn() {
var one = 1;
function inner() {
one += 1;
console.log(one);
}
return inner;
}
var outer = fn();
outer();
//
2
outer();
//
3
outer();
//
4
四. 闭包与变量
闭包容许内层函数引用父函数中的变量,但该变量是最终值。
鼠标移过每个li元素时,控制台输出的值都是3,而不是咱们指望的元素下标。当mouseover事件调用监听函数时,首先在匿名函数内部查找i是否认义,结果没找到,所以向上查找,在全局环境中找到i,而且i的值是3(循环后的值)。所以每次输出的都是3。
/*
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
*/
var lists = document.getElementsByTagName("li");
for(
var i=0; i<lists.length; i++) {
lists[i].onmouseover =
function() {
console.log(i);
}
}
注意:此处的闭包,并非函数嵌套函数的形式,而是匿名函数包含在全局环境中的形式。
针对上述代码,有三种方法改进,使得鼠标移动到li元素上时,控制台输出对应的下标值。
1)当即执行的匿名函数
var lists = document.getElementsByTagName("li");
for (
var i = 0; i < lists.length; i++) {
(
function(index) {
lists[i].onmouseover =
function() {
console.log(index);
};
})(i);
}
2)在DOM元素上绑定$$index属性记录下标
var lists = document.getElementsByTagName("li");
for (
var i = 0; i < lists.length; i++) {
lists[i].$$index = i;
lists[i].onmouseover =
function() {
console.log(
this.$$index);
};
}
3)
var lists = document.getElementsByTagName("li");
for (
var i = 0; i < lists.length; i++) {
eventListener(lists[i],i);
}
function eventListener(list,index) {
list.onmouseover =
function() {
console.log(index);
}
}
时间:2014-10-23
地点:合肥
引用:http://www.cnblogs.com/rainman/archive/2009/05/04/1448899.html