(转载)JavaScript中匿名函数,函数直接量和闭包


Posted in Javascript onMay 08, 2007

原文出处: http://www.dnew.cn/post/196.htm

先看下下面几种写法

1.function f(x){return x*x;};f(x);

2.(function(x){return x*x;})(x);

3.(function(x){return x*x;}(x));

第一种我们应该都很熟悉了,这是我们经常使用的写法。第二第三种都是匿名函数的写法。

--------------------------------------------------------------------------------

第二种
可以这样理解:

var f=function(x) {return x*x;};f()

那我们不通过f这个变量来引用函数就是

function(){}()

然而这样肯定是错误的就像

var f=1+2;
f=f*0;

var f=1+2*0;

结果不同一样。
要得到正确结果只能:

f=(1+2)*0;

也就是要明确的标识出程序块,即:

(function(){})()

肯你有疑问:括号“()”到底是不是起到了标识代码块的作用?
我们可以用JavaScript的内置函数检测一下!
举一个最简单的例子:

alert(4)

这段代码会弹出提示内容是“4”
改成这样
(alert)(4)

可以看到执行的效果和上一段代码一样。

这种形式的函数执行也被很多JavaScript框架所采用。

--------------------------------------------------------------------------------

第三种,如果你用过jsvm框架的话就会发现里面的代码使用了这种形式。
那如何解释第三种情况呢?
为了弄明白浏览器是如何理解这样的写法的,我们可以利用一下Mozilla Firefox的错误控制台功能。
在代码中插入一段错误代码,代码段如下:

(function(s){s+s}(1)).splice();

打开Mozilla Firefox的错误控制台,可以看到有如下的错误提示

错误: (function (s) {})(1) has no properties
源文件:file:///C:/Documents…….html
行:18

可以认为,浏览器对于
(function(s){s+s}(1))
这样的代码按照

(function (s) {s+s})(1)
来解析的。

--------------------------------------------------------------------------------

到此可能你有这样的认识:

function f(x){return x*x;};f(x);==(function(x){return x*x;})(x);==(function(x){return x*x;}(x));

但是他们还是有区别的,
首先,对于像第二和第三种形式,其它的函数和代码是不可能调用所定义的函数的,有一种说发把这样的函数称为匿名函数或者函数直接量。
其次,第二和第三种形式执行的函数,中间变量不会污染到全局命名空间,你可以把中间的代码看作纯粹的子过程调用。
当然使用后面两种形式的函数定义可以很容易的实现闭包。
看一个例子:

/*
http://jibbering.com/faq/faq_notes/closures.html(Dnew.CN注)
A global variable - getImgInPositionedDivHtml - is declared and
  assigned the value of an inner function expression returned from
  a one-time call to an outer function expression.

  That inner function returns a string of HTML that represents an
  absolutely positioned DIV wrapped round an IMG element, such that
  all of the variable attribute values are provided as parameters
  to the function call:-
*/
var getImgInPositionedDivHtml = (function(){
   /* The - buffAr - Array is assigned to a local variable of the
      outer function expression. It is only created once and that one
      instance of the array is available to the inner function so that
      it can be used on each execution of that inner function.

      Empty strings are used as placeholders for the date that is to
      be inserted into the Array by the inner function:-
   */
   var buffAr = [
       '<div id="',
       '',   //index 1, DIV ID attribute
       '" style="position:absolute;top:',
       '',   //index 3, DIV top position
       'px;left:',
       '',   //index 5, DIV left position
       'px;width:',
       '',   //index 7, DIV width
       'px;height:',
       '',   //index 9, DIV height
       'px;overflow:hidden;\"><img src=\"',
       '',   //index 11, IMG URL
       '\" width=\"',
       '',   //index 13, IMG width
       '\" height=\"',
       '',   //index 15, IMG height
       '\" alt=\"',
       '',   //index 17, IMG alt text
       '\"><\/div>'
   ];
   /* Return the inner function object that is the result of the
      evaluation of a function expression. It is this inner function
      object that will be executed on each call to -
      getImgInPositionedDivHtml( ... ) -:-
   */
   return (function(url, id, width, height, top, left, altText){
       /* Assign the various parameters to the corresponding
          locations in the buffer array:-
       */
       buffAr[1] = id;
       buffAr[3] = top;
       buffAr[5] = left;
       buffAr[13] = (buffAr[7] = width);
       buffAr[15] = (buffAr[9] = height);
       buffAr[11] = url;
       buffAr[17] = altText;
       /* Return the string created by joining each element in the
          array using an empty string (which is the same as just
          joining the elements together):-
       */
       return buffAr.join('');
   }); //:End of inner function expression.
})();
/*^^- :The inline execution of the outer function expression. */

Javascript 相关文章推荐
JavaScript中使用构造函数实现继承的代码
Aug 12 Javascript
超简单JS二级、多级联动的简单实例
Feb 18 Javascript
浅谈javascript中createElement事件
Dec 05 Javascript
js中字符串编码函数escape()、encodeURI()、encodeURIComponent()区别详解
Apr 01 Javascript
jQuery获取多种input值的简单实现方法
Jun 20 Javascript
浅谈js算法和流程控制
Dec 29 Javascript
Node.js使用NodeMailer发送邮件实例代码
Mar 06 Javascript
Express下采用bcryptjs进行密码加密的方法
Feb 07 Javascript
JS实现动态倒计时功能(天数、时、分、秒)
Dec 12 Javascript
vue使用exif获取图片旋转,压缩的示例代码
Dec 11 Vue.js
详解如何使用Node.js实现热重载页面
May 06 Javascript
Rust中的Struct使用示例详解
Aug 14 Javascript
阻止JavaScript事件冒泡传递(cancelBubble 、stopPropagation)
May 08 #Javascript
延时重复执行函数 lLoopRun.js
May 08 #Javascript
用js判断浏览器是否是IE的比较好的办法
May 08 #Javascript
[全兼容哦]--实用、简洁、炫酷的页面转入效果loing
May 07 #Javascript
javascript之水平横向滚动歌词同步的应用
May 07 #Javascript
javascript之ESC(第二类混淆)
May 06 #Javascript
通过Unicode转义序列来加密,按你说的可以算是混淆吧
May 06 #Javascript
You might like
php添加数据到xml文件的简单例子
2016/09/08 PHP
Yii2框架实现数据库常用操作总结
2017/02/08 PHP
让 JavaScript 轻松支持函数重载 (Part 2 - 实现)
2009/08/04 Javascript
跨域表单提交状态的变相判断代码
2009/11/12 Javascript
jquery 可拖拽的窗体控件实现代码
2010/03/21 Javascript
Node.js异步I/O学习笔记
2014/11/04 Javascript
jQuery过滤选择器用法分析
2015/02/10 Javascript
JS实现仿新浪微博发布内容为空时提示功能代码
2015/08/19 Javascript
基于jQuery实现Div窗口震动特效代码-代码简单
2015/08/28 Javascript
JS与jQ读取xml文件的方法
2015/12/08 Javascript
jQuery height()、innerHeight()、outerHeight()函数的区别详解
2016/05/23 Javascript
AngularJS实现表单验证功能
2017/01/09 Javascript
Angular1.x自定义指令实例详解
2017/03/01 Javascript
Vue学习笔记进阶篇之函数化组件解析
2017/07/21 Javascript
微信小程序picker组件下拉框选择input输入框的实例
2017/09/20 Javascript
解决JQuery全选/反选第二次失效的问题
2017/10/11 jQuery
layui 监听表格复选框选中值的方法
2018/08/15 Javascript
GOJS+VUE实现流程图效果
2018/12/01 Javascript
layui-table对返回的数据进行转变显示的实例
2019/09/04 Javascript
vue 组件销毁并重置的实现
2020/01/13 Javascript
浅谈vue中$event理解和框架中在包含默认值外传参
2020/08/07 Javascript
js面向对象方式实现拖拽效果
2021/03/03 Javascript
wxPython事件驱动实例详解
2014/09/28 Python
使用paramiko远程执行命令、下发文件的实例
2017/10/01 Python
python版大富翁源代码分享
2018/11/19 Python
python中aioysql(异步操作MySQL)的方法
2019/04/11 Python
canvas实现图片马赛克的示例代码
2018/03/26 HTML / CSS
下面代码从性能上考虑,有什么问题
2015/04/03 面试题
毕业生的自我评价分享
2013/12/18 职场文书
护理人员的自我评价分享
2014/03/15 职场文书
村党组织公开承诺书
2015/04/30 职场文书
幼儿园教学工作总结2015
2015/05/12 职场文书
离婚案件被告代理词
2015/05/23 职场文书
Vue详细的入门笔记
2021/05/10 Vue.js
zabbix agent2 监控oracle数据库的方法
2021/05/13 Oracle
python调试工具Birdseye的使用教程
2021/05/25 Python