自调用函数

自调用函数(self-invoking funciton)就是函数定义完之后会立即运行的函数. 最常见的写法是:

(function() {
// function body...
}());
// or
(function() {
// function body...
})();

自调用函数的另一种写法

不过最近看某个库的源代码(暂时忘了是哪个了=,.=)时发现有如下写法:

+function() {
// function body
}();

感到神奇, 于是SO了一下, 原来这是另一种自调用函数的写法.

+号使得js解释器认为它现在在处理的是一个表达式, 而非函数定义. 如果不写这个+号, 解释器会按照函数定义去处理, 并认为后面的()是语法错误.

其实除了+号, -, !, ~以及其他一元操作符都可以产生相同的效果.

与要在用()把函数包起来的常用写法相比, 这种写法的好处(也许)就是只要在前面加个+就行了, 更省事儿. 当然, 最后的();是一定不能少的.

需要注意的问题

主要注意的是, 一定不能省略自调用函数前面赋值语句的;.

如果自调用函数前面是函数定义, 一切正常:

function x() { console.log(1); } +function () { console.log(2); }();
// 2

但是如果它前面是个赋值语句, 你的代码非常容易出bug, 即使是用()包裹自调用函数也不行.

var s = {}; s.a = function() { console.log(1); } + function() { s.a(); }();
// Uncaught TypeError: s.a is not a function(…)
var s = {}; s.a = function() { console.log(1); } (function() { s.a(); }());
// Uncaught TypeError: s.a is not a function(…)
var a = function() { console.log(1); } + function() { console.log(2); }();
// 2
// a is “function () { console.log(1); }undefined”
var a = function() { console.log(1); } (function() { console.log(2); }());
// 2 1
// a is `undefined`!!
var a = function() { console.log(1); } (+ function() { console.log(2); }());
// 2 1
// a is `undefined`!!

我以前曾经遇到这个bug, 但是并不知道发生了什么, 只是很奇怪为什么自调用函数前面的那个函数会自动执行... 后来我无奈用了下面这种弱鸡的形式

function init() {
// function body
}
init();

正确的做法应该是:

var x = function() {
console.log(1);
}; // <---------------- here! DO NOT omit this semicolon!
+ function() {
console.log(2);
}();

我还听说有minify之前运行得好好的, minify之后就出bug, 也是因为少了;.

综上, 在每句赋值语句后面加上;号是一个很重要的好习惯!

自调用函数前面的;

2016/4/14更新

今天瞟了一眼platform.js的源代码, 看到最外层是

;(function() {
// function body...
}.call(this));

SO了一下, 这是一种更加保险的方式.

假设两个文件的内容分别是:

// File A
(function(){console.log(1);})()
// File B
(function(){console.log(2);})()

那么这两个文件打包到一起就会报错

(function(){console.log(1);})()(function(){console.log(2);})()
// Uncaught TypeError: (intermediate value)(...) is not a function(…)

当然, 这个错误也是由于两个文件中不好的代码习惯导致的--就是最后没有加;. 而在(function...前面写上;就可以100%确保自调用函数的正常执行.

参考

  1. Does omitting semicolons affect performance in JavaScript?
  2. Why should I use a semicolon after every function in javascript?

JavaScript中的自调用函数的更多相关文章

  1. [转]Javascript中的自执行函数表达式

    [转]Javascript中的自执行函数表达式 本文转载自:http://www.ghugo.com/javascript-auto-run-function/ 以下是正文: Posted on 20 ...

  2. 深入理解javascript中的立即执行函数(function(){…})()

    投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...

  3. 使用Ajax在javascript中调用后台C#函数

    使用Ajax在javascript中调用后台C#函数 最近一段时间在紧跟一个网站的项目,数据库中用户表的UserName要求是唯一的,所以当用户选定一个用户名进行注册时要首先检查该用户名是否已被占用, ...

  4. 在javascript中关于变量与函数的提升

    在javascript中关于变量与函数的提升 一.简介 在javascript中声明变量与函数的执行步骤: 1.先预解析变量或函数声明代码,会把用var声明的变量或者函数声明的代码块进行提升操作 2. ...

  5. javascript中的立即执行函数(function(){…})()

    javascript中的立即执行函数(function(){…})() 深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包 ...

  6. 深入理解javascript中的立即执行函数

    这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包住业务代码,使用jquery时比较常见,需要的朋友可以 ...

  7. JavaScript中的内置函数

    JavaScript中的内置函数 制作人:全心全意 在使用JavaScript语言时,除了可以自定义函数之外,还可以使用JavaScript的内置函数,这些内置函数是由JavaScript语言自身提供 ...

  8. JavaScript 中对变量和函数声明提前的演示样例

    如题所看到的,看以下的演示样例(能够使用Chrome浏览器,然后F12/或者右键,审查元素.调出开发人员工具,进入控制台console输入)(使用技巧: 控制台输入时Shift+Enter能够中途代码 ...

  9. javascript中的this与函数讲解

    前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码, ...

随机推荐

  1. js调用本地 exe

      js方法 function Run(strPath) //only for ie { try { var objShell = new ActiveXObject("wscript.sh ...

  2. 【JAVA】浅谈java内部类

    一.什么是内部类? 到底什么是内部类呢?通俗的讲,就是在类内部定义的类,包括定义在一个类的方法外面.方法里面或者代码块中. 二.为什么要使用内部类? 为什么我们要不走寻常路,把一个类定义在另一个类的内 ...

  3. spring.net 和 mybatis.net

    demo是整合现有的spring.net 和 mybatis.net 完成的控制台程序,需要注意的地方:关于Config文件夹中的config文件的属性设定:同时保证Providers.config默 ...

  4. 学习之spring注解DI疑惑

    接口定义 package com; public interface IPaly { void say(); } 接口实现类 package com; import org.springframewo ...

  5. 创建Unity新项目并编译成游戏程序

    注:本人所使用的Unity版本为:Unity5.3.5f1,所使用的VS版本为:Visual.Studio.2013.Ultimate 折腾了快一个月了,终于有时间做自己的啦,哈哈: ) 步骤一:启动 ...

  6. 某deed笔试题

    1.  删除ra,输入s,然后从前往后扫,遇到直接删除,O(n),算水题吧. 2. 矩阵乘法,看完题,感觉这么简单,估计有什么套路,仔细再读一遍,发现真是水题,50*50*50=125000,在2s时 ...

  7. DLL详解及Denpendcy Walker的使用

    下面的文章被N次转载,为了尊重原作,\(^o^)/~,贴出最早发布这篇文章的地址及作者.   动态链接库 Windows的活动大陆 2006-07-26 09:21  作者:狂ρκ来源:电脑爱好者 在 ...

  8. leetcode Largest Rectangle in Histogram 单调栈

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4052343.html 题目链接 leetcode Largest Rectangle in ...

  9. php 工作模式

    PHP运行模式 1.cgi通用网关接口 (少用)2.fast-cgi常驻型的 cgi [ngixn常用]3.cli命令运行 (命令行用得多)4.web模块模式(apache等web服务器的运行模式)[ ...

  10. stop() 是用于停止动画 :animated 用于判断动画是否在进行中

    stop() 是用于停止动画 if($("element").is(":animated"))  用于判断动画是否在进行中