js中匿名函数的创建与调用方法分析


Posted in Javascript onDecember 19, 2014

本文实例分析了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程序设计有所帮助。

Javascript 相关文章推荐
JS 对象介绍
Jan 20 Javascript
js中的push和join方法使用介绍
Oct 08 Javascript
JavaScript数组对象实现增加一个返回随机元素的方法
Jul 27 Javascript
jquery实现点击查看更多内容控制段落文字展开折叠效果
Aug 06 Javascript
很酷的星级评分系统原生JS实现
Aug 25 Javascript
深入理解 JavaScript 中的 JSON
Apr 06 Javascript
JavaScript订单操作小程序完整版
Jun 23 Javascript
解决Vue编译时写在style中的路径问题
Sep 21 Javascript
jQuery选择器之子元素过滤选择器
Sep 28 jQuery
Vue使用Clipboard.JS在h5页面中复制内容实例详解
Sep 03 Javascript
JS自定义对象创建与简单使用方法示例
Jan 15 Javascript
vue @click.native 绑定原生点击事件
Apr 22 Vue.js
浅谈Javascript中匀速运动的停止条件
Dec 19 #Javascript
浅谈Javascript如何实现匀速运动
Dec 19 #Javascript
Javascript添加监听与删除监听用法详解
Dec 19 #Javascript
Javascript 实现图片无缝滚动
Dec 19 #Javascript
使用JavaScript获取地址栏参数的方法
Dec 19 #Javascript
JS获取各种宽度、高度的简单介绍
Dec 19 #Javascript
JQuery右键菜单插件ContextMenu使用指南
Dec 19 #Javascript
You might like
PHP基础知识介绍
2013/09/17 PHP
ThinkPHP3.1.3版本新特性概述
2014/06/19 PHP
php 中self,this的区别和操作方法实例分析
2019/11/04 PHP
JQuery 选项卡效果(JS与HTML的分离)
2010/04/01 Javascript
jQuery选择器简明总结(含用法实例,一目了然)
2014/04/25 Javascript
js使用onmousemove和onmouseout获取鼠标坐标的方法
2015/03/31 Javascript
TypeScript具有的几个不同特质
2015/04/07 Javascript
浅谈javascript语法和定时函数
2015/05/03 Javascript
不同js异步函数同步的实现方法
2016/05/28 Javascript
bootstrapfileinput实现文件自动上传
2016/11/08 Javascript
JavaScript获取中英文混合字符串长度的方法示例
2017/02/04 Javascript
React Native实现进度条弹框的示例代码
2017/07/17 Javascript
JS写XSS cookie stealer来窃取密码的步骤详解
2017/11/20 Javascript
Vue的事件响应式进度条组件实例详解
2018/02/04 Javascript
微信小程序自定义带价格显示日历效果
2018/12/29 Javascript
微信小程序中的video视频实现 自定义播放按钮、封面图、视频封面上文案
2020/01/02 Javascript
Vue解析剪切板图片并实现发送功能
2020/02/04 Javascript
[36:54]Mineski vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
在Python的Flask框架下使用sqlalchemy库的简单教程
2015/04/09 Python
简述:我为什么选择Python而不是Matlab和R语言
2017/11/14 Python
Python3.7中安装openCV库的方法
2018/07/11 Python
Pandas之Fillna填充缺失数据的方法
2019/06/25 Python
python输出带颜色字体实例方法
2019/09/01 Python
Python使用Tkinter实现转盘抽奖器的步骤详解
2020/01/06 Python
Python如何使用paramiko模块连接linux
2020/03/18 Python
Python内存映射文件读写方式
2020/04/24 Python
详解python中GPU版本的opencv常用方法介绍
2020/07/24 Python
浅谈Python 钉钉报警必备知识系统讲解
2020/08/17 Python
HTML5的postMessage的使用手册
2018/12/19 HTML / CSS
幼儿园保教管理制度
2014/02/03 职场文书
网管求职信
2014/03/03 职场文书
表彰会主持词
2014/03/26 职场文书
大班开学家长寄语
2014/04/04 职场文书
机械制造专业大学生自我鉴定
2014/09/19 职场文书
2014业务员年终工作总结
2014/12/09 职场文书
Java 实现限流器处理Rest接口请求详解流程
2021/11/02 Java/Android