话不多说,先看代码
<script>
getajax = (function(){
alert("hello");
function dosomething(){
alert("world");
}
return {do : dosomething};
})();//此处函数已经执行完毕,所以getajax是返回值,而不是函数
getajax.do();//此处执行dosomething函数
</script>
此处代码的执行结果会弹出两条语句,”hello”和“world”
getajax是一个变量,是函数的返回值,是对象{do: dosomething},
var hello = function(){
};
或
function hello(){
};
是函数声明方法,只会声明函数,而不会执行函数
var hello = function(){
};
或
function hello(){
};
hello();
上文中hello()才会执行函数
但是这样的函数声明需要一个全局变量才能调用,如是人们想,
function(){}();
这样是不是可以呢?很可惜,这样是不行的,因为function(){}只是函数声明语句,编译器会认为在函数声明语句后面直接加()是语法错误。
(function(){})();
上面加了括号之后编译器会认为上文是一个表达式,会按表达式的方式立即执行函数,所以上文可以。实际上,生成表达式的方式很多,比如
(function(){}());
+function(){}();
!function(){}();
void(function(){}());
都可以,注意void不会返回返回值。
文章最开始的代码,因为getajax= 后面已经是表达式了,所以,下面的代码会产生同样的结果
<script>
getajax = function(){
alert("hello");
function dosomething(){
alert("world");
}
return {do:dosomething};
}();
getajax.do();
如果去掉了
getajax =
那么括号就是必须的,否则编译器会认为这是一个函数声明语句,而后面的括号是语法错误。
此处的getajax是用来接收函数的返回值的,它不是一个函数,是一个对象,即{ do:dosomething}。
OVER
续:09/05/2016
前文讲到如何在声明函数后立即执行函数,那么如何如果要向声明的函数传递参数要怎么办呢,
(function(param) {
alert(param);
})("hello");
只需要在括号中传入相应的参数即可。
在js中,参数不仅可以是string,还可以是对象,于是
(function($){
...
})(jQuery);
这个方法将jQuery对象作为参数传入函数,而
是函数的形参,其作用类似于jQuery的noconflict方法,可以在方法内部使用
,防止与其它js类库冲突。
还可以更进一步,使用函数作为函数的参数
(function(factory){
factory("hello");
})(function(para){
alert(para);
});
此处将匿名函数
function(para){alert(para);}
作为参数传入第一个函数,factory是形参,而匿名函数是实参,在第一个函数内部再次调用匿名函数。所以我们也可以这样
(function(factory){
factory(jQuery);
})(function($){...})
这样,可以在第一个匿名函数内将jQuery传入第二个匿名函数,而在第二个函数内部使用 ,而且这个用法可以根据需要为 传入不同的实参,可以是jQuery,也可以是其它的prototype等。
小结:(function(){})()本来是非常简单的声明完成执行,但是由于js参数类型的多变,形成了非常复杂与多变的结构,但其最初的原理还是一样。