js中匿名函数的创建与调用方法分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
js中匿名函数的创建与调⽤⽅法分析
本⽂实例分析了js中匿名函数的创建与调⽤⽅法。
分享给⼤家供⼤家参考。
具体实现⽅法如下:
匿名函数就是没有名字的函数了,也叫闭包函数(closures),允许临时创建⼀个没有指定名称的函数。
最经常⽤作回调函数(callback)参数的值,很多新⼿朋友对于匿名函数不了解。
这⾥就来分析⼀下。
function 函数名(参数列表){函数体;}
如果是创建匿名函数,那就应该是:
function(){函数体;}
因为是匿名函数,所以⼀般也不会有参数传给他。
为什么要创建匿名函数呢?在什么情况下会使⽤到匿名函数。
匿名函数主要有两种常⽤的场景,⼀是回调函数,⼆是直接执⾏函数。
回调函数,像ajax的异步操作,就需要回调函数。
这⾥就不详解。
关于直接执⾏函数,我看⼀个例⼦就明⽩了:
复制代码代码如下:
<script language="javascript">
var a = "a";
(function(){
var a="b";
alert(a);
})();
alert(a);
</script>
在上⾯这段代码中,会顺序输出两个alert框。
第⼀个alert框内容为b,第⼆个为a。
⼤家看到什么好处了吗?对的,使⽤函数直接执⾏可以限定变量的作⽤域,使不同脚本的相同变量可以得以共存。
下⾯,我们先初步了解⼀下和匿名函数相关的概念。
函数声明(function 语句),要使⽤⼀个函数,我们就得⾸先声明它的存在。
⽽我们最常⽤的⽅式就是使⽤function 语句来定义⼀个函数,如:
复制代码代码如下:
function abc(){
// code to process
}
function abc(){ // code to process }
当然,你的函数也可以是带参数的,甚⾄是带返回值的。
复制代码代码如下:
view plaincopy to clipboardprint?
function abc(x,y){
return x+y;
}
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","y","return x*y;");
alert(abc(2,3)); // "6"
相信⼤家现在对如何声明⼀个函数应该是有所了解了。
那么什么才是匿名函数呢?
声明匿名函数
顾名思义,匿名函数就是没有实际名字的函数。
例如,我们把上⾯的例⼦中,函数的名字去掉,再判断⼀下他是不是⼀个函数:
复制代码代码如下:
alert(typeof function(){});// "function"
alert(typeof function(x,y){return x+y;});// "function"
alert(typeof new Function("x","y","return x*y;"))// "function"
alert(typeof function(){});// "function"
alert(typeof function(x,y){return x+y;});// "function"
alert(typeof new Function("x","y","return x*y;"))// "function"
我们可以很容易地看到,它们全都是Function 对象,换⾔之,他们都是函数,但是他们都有⼀个特点—— 没有名字。
所以我们把他们称作“ 匿名函数” 。
然⽽,正因为他们没有“ 名字” ,我们也没有办法找到他们。
这就引申了如何去调⽤⼀个匿名函数的问题了。
匿名函数的调⽤
要调⽤⼀个函数,我们必须要有⽅法定位它,引⽤它。
所以,我们会需要帮它找⼀个名字。
例如:
复制代码代码如下:
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","y","return x*y;"))(2,3));// "6"
很多⼈或许会奇怪,为什么这种⽅法能成功调⽤呢?觉得这个应⽤奇怪的⼈就看⼀下我以下这段解释吧。
⼤家知道⼩括号的作⽤吗?⼩括号能把我们的表达式组合分块,并且每⼀块,也就是每⼀对⼩括号,都有⼀个返回值。
这个返回值实际上也就是⼩括号中表达式的返回值。
所以,当我们⽤⼀对⼩括号把匿名函数括起来的时候,实际上⼩括号对返回的,就是⼀个匿名函数的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= 都去掉。
)
闭包
闭包是什么?闭包是指某种程序语⾔中的代码块允许⼀级函数存在并且在⼀级函数中所定义的⾃由变量能不被释放,直到⼀级函数被释放前,⼀级函数外也能应⽤这些未释放的⾃由变量。
怎样?看得⼀头冒汗吧…… 没事,我也是(虽然是我是了解的,只是表达能⼒的问题)。
让我们换个更加简单的⽅法说明:闭包,其实是⼀种语⾔特性,它是指的是程序设计语⾔中,允许将函数看作对象,然后能像在对象中的操作般在函数中定义实例(局部)变量,⽽这些变量能在函数中保存到函数的实例对象销毁为⽌,其它代码块能通过某种⽅式获取这些实例(局部)变量的值并进⾏应⽤扩展。
不知道这么再解释后会否更加清晰,如果还是不明⽩,那么我们再简化⼀下:闭包,其实就是指程序语⾔中能让代码调⽤已运⾏的函数中所定义的局部变量。
现在我们看⼀个例⼦:
复制代码代码如下:
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” 未定义!
看到这⾥,你能判断究竟jQuery 的那个代码⽚段是否闭包了吗?
以我的理解来说吧。
是否应⽤了闭包特性,必须确定该段代码有没有最重要的要素:未销毁的局部变量。
那么很显然,没有任何实现的匿名函数不可能应⽤了闭包特性。
但如果匿名函数⾥⾯有实现呢?那也还得确定它的实现中有没有⽤到那些未销毁的局部变量。
所以如果问你那个开篇中的jQuery 代码⽚段是应⽤了JS ⾥的什么特性?那么它只是匿名函数与匿名函数的调⽤⽽已。
但是,它隐含了闭包的特性,并且随时可以实现闭包应⽤。
最常见的⽤法:
复制代码代码如下:
(function() {
alert('water');
})();
当然也可以带参数:
复制代码代码如下:
(function(o) {
alert(o);
})('water');
想⽤匿名函数的链式调⽤?很简单:
复制代码代码如下:
(function(o) {
alert(o);
return arguments.callee;
})('water')('down');
常见的匿名函数都知道了,看看不常见的:
复制代码代码如下:
~(function(){
alert('water');
})();//写法有点酷~
void function(){
alert('water');
}();//据说效率最⾼~
+function(){
alert('water');
}();
-function(){
alert('water');
}();
~function(){
alert('water');
}();
!function(){
alert('water');
}();
(function(){
alert('water');
}());//有点强制执⾏的味道~
希望本⽂所述对⼤家的javascript程序设计有所帮助。