JavaScript中的自调用函数
自调用函数
自调用函数(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%确保自调用函数的正常执行.