匿名函数
1、定义
匿名函数就是没有名字的函数了,也叫闭包函数(closures),允许 临时创建⼀个没有指定名称的函数。最经常⽤作回调函数(callback)参数的值。2、创建⽅式
⼀般有名字的函数的创建⽅式是:function 函数名(参数列表){函数体;}如果是创建匿名函数,那就应该是:function(){函数体;}
很明显能看出区别就是,匿名函数没有名字。因为是匿名函数,所以⼀般也不会有参数传给他。3、匿名函数的作⽤
为什么要创建匿名函数呢?在什么情况下会使⽤到匿名函数。匿名函数主要有两种常⽤的场景,⼀是回调函数,⼆是直接执⾏函数。回调函数,像ajax的异步操作,就需要回调函数。这⾥就不详解。关于直接执⾏函数,看⼀个例⼦就明⽩了:
在上⾯这段代码中,会顺序输出两个alert框。第⼀个alert框内容为b,第⼆个为a。⼤家看到什么好处了吗?对的,使⽤函数直接执⾏可以限定变量的作⽤域,使不同脚本的相同变量可以得以共存。4、和匿名函数相关的概念
下⾯,我们先初步了解⼀下和匿名函数相关的概念。
函数声明(function 语句),要使⽤⼀个函数,我们就得⾸先声明它的存在。⽽我们最常⽤的⽅式就是使⽤function 语句来定义⼀个函数,如:
function abc(){// code to process}
当然,你的函数也可以是带参数的,甚⾄是带返回值的。function abc(x,y){return x+y;}
但是,⽆论你怎么去定义你的函数,JS 解释器都会把它翻译成⼀个Function 对象。例如,你在定义上⾯的其中⼀个例⼦的函数号,再输⼊如下代码:
alert(typeof abc);// \"function\"
你的浏览器就会弹出提⽰框,提⽰你abc 是⼀个Function 对象。那么Function 对象究竟是什么呢?Function 对象
Function 对象是JavaScript ⾥⾯的固有对象,所有的函数实际上都是⼀个Function 对象。我们先看看,Function 对象能不能直接运⽤构造函数创建⼀个新的函数呢?答案是肯定的。例如:var abc = new Function(\"x\alert(abc(2,3)); // \"6\"声明匿名函数
顾名思义,匿名函数就是没有实际名字的函数。例如,我们把上⾯的例⼦中,函数的名字去掉,再判断⼀下他是不是⼀个函数:alert(typeof function(){});// \"function\"
alert(typeof function(x,y){return x+y;});// \"function\"
alert(typeof new Function(\"x\alert(typeof function(){});// \"function\"
alert(typeof function(x,y){return x+y;});// \"function\"
alert(typeof new Function(\"x\
我们可以很容易地看到,它们全都是Function 对象,换⾔之,他们都是函数,但是他们都有⼀个特点—— 没有名字。所以我们把他们称作“匿名函数” 。然⽽,正因为他们没有“ 名字” ,我们也没有办法找到他们。这就引申了如何去调⽤⼀个匿名函数的问题了。5、如何调⽤匿名函数
要调⽤⼀个函数,我们必须要有⽅法定位它,引⽤它。所以,我们会需要帮它找⼀个名字。例如:var abc=function(x,y){return x+y;}
alert(abc(2,3)); // \"5\"
上⾯的操作其实就等于换个⽅式去定义函数,这种⽤法是我们⽐较频繁遇到的。例如我们在设定⼀个DOM 元素事件处理函数的时候,我们通常都不会为他们定名字,⽽是赋予它的对应事件引⽤⼀个匿名函数。
对匿名函数的调⽤其实还有⼀种做法,也就是我们看到的jQuery ⽚段—— 使⽤() 将匿名函数括起来,然后后⾯再加⼀对⼩括号(包含参数列表)。我们再看⼀下以下例⼦:
alert((function(x,y){return x+y;})(2,3));// \"5\"
alert((new Function(\"x\
很多⼈或许会奇怪,为什么这种⽅法能成功调⽤呢?觉得这个应⽤奇怪的⼈就看⼀下我以下这段解释吧。
⼤家知道⼩括号的作⽤吗?⼩括号能把我们的表达式组合分块,并且每⼀块,也就是每⼀对⼩括号,都有⼀个返回值。这个返回值实际上也就是⼩括号中表达式的返回值。所以,当我们⽤⼀对⼩括号把匿名函数括起来的时候,实际上⼩括号对返回的,就是⼀个匿名函数的
Function 对象。因此,⼩括号对加上匿名函数就如同有名字的函数般被我们取得它的引⽤位置了。所以如果在这个引⽤变量后⾯再加上参数列表,就会实现普通函数的调⽤形式。
不知道以上的⽂字表述⼤家能不能看明⽩,如果还是理解不了的话,再看⼀下以下的代码试试吧。var abc=function(x,y){return x+y;};// 把匿名函数对象赋给abc
// abc 的constructor 就和匿名函数的constructor ⼀样了。也就是说,两个函数的实现是⼀样的。alert((abc).constructor==(function(x,y){return x+y;}).constructor);
PS :constructor 是指创建对象的函数。也就是函数对象所代表的函数体。
总之,将其(被⼩括号包含的匿名函数)理解为括号表达式返回的函数对象,然后就可以对这个函数对象作正常的参数列表调⽤了。(前⾯这⾥犯了个错误,只有函数表达式还是不能直接调⽤函数的,去掉匿名函数括号必须要伴随将表达式赋值。也就是(function(){alert(1)})() 应该是与 a=function(){alert(1)}() 等价,不能连a= 都去掉。)6、闭包
闭包是什么?闭包是指某种程序语⾔中的代码块允许⼀级函数存在并且在⼀级函数中所定义的⾃由变量能不被释放,直到⼀级函数被释放前,⼀级函数外也能应⽤这些未释放的⾃由变量。
让我们换个更加简单的⽅法说明:闭包,其实是⼀种语⾔特性,它是指的是程序设计语⾔中,允许将函数看作对象,然后能像在对象中的操作般在函数中定义实例(局部)变量,⽽这些变量能在函数中保存到函数的实例对象销毁为⽌,其它代码块能通过某种⽅式获取这些实例(局部)变量的值并进⾏应⽤扩展。
不知道这么再解释后会否更加清晰,如果还是不明⽩,那么我们再简化⼀下:闭包,其实就是指程序语⾔中能让代码调⽤已运⾏的函数中所定义的局部变量。
var abc=function(y){
var x=y;// 这个是局部变量return function(){
alert(x++);// 就是这⾥调⽤了闭包特性中的⼀级函数局部变量的x ,并对它进⾏操作alert(y--);// 引⽤的参数变量也是⾃由变量}}(5);// 初始化abc();// \"5\" \"5\"abc();// \"6\" \"4\"abc();// \"7\" \"3\"
alert(x);// 报错!“x” 未定义!
以我的理解来说吧。是否应⽤了闭包特性,必须确定该段代码有没有最重要的要素:未销毁的局部变量。那么很显然,没有任何实现的匿名函数不可能应⽤了闭包特性。最常见的⽤法:(function() {alert('water');})();
当然也可以带参数:(function(o) {alert(o);})('water');
想⽤匿名函数的链式调⽤?很简单:(function(o) {alert(o);
return arguments.callee;})('water')('down');7、不常见的匿名函数
常见的匿名函数都知道了,看看不常见的:~(function(){alert('water');})();//写法有点酷~
void function(){alert('water');
}();//据说效率最⾼~
+function(){alert('water');}();
-function(){alert('water');}();
~function(){alert('water');}();
!function(){alert('water');}();
(function(){alert('water');
}());//有点强制执⾏的味道~
因篇幅问题不能全部显示,请点此查看更多更全内容