1 (function(){...})() 3 (function(){...}())
这是两种js立即执行函数的常见写法。
基本概念:
函数声明:function fname(){...}; 使用function关键字声明一个函数,再指定一个函数名。
函数表达式:var fname=function(){...}; 使用function关键字声明一个函数,但未给函数命名,最后将匿名函数赋予给一个变量。
匿名函数:function(){}; 使用function关键字声明一个函数,但未给函数命名。(匿名函数也属于函数表达式。)
(匿名函数作用很多,赋予一个变量则创建函数,赋予一个事件则成为事件处理程序等。。)
关于函数声明和函数表达式的区别:
1:函数声明的Function declaration Hoisting(换成人话就是函数声明提升),函数表达式不具备这点,它需要被js代码解析到当前这行时才可以调用。
2:函数表达式后边加 ()立即调用该函数,函数声明不可以,它只能以fname()调用。
例子:
1 fName(); 2 function fName(){...}//正确,函数声明提升,所以 fName()可以写在函数声明之前。 3 4 fName(); 5 var fName=function(){...}//错误,函数表达式不具备函数声明提升。 6 7 var fName=function(){...}();//正确,函数表达式后边加()立即调用函数。 8 9 function fName(){...}();//错误,函数声明必须用fName()调用。
//这行代码被解析为两部分: 1函数声明 function fName(){...}, 2分组表达式(),这表达式有误,因为括号内没有表达式,
function (){...}();//匿名函数不可以这么调用,因为function(){...}被当做了声明,声明不可以直接()调用。
顺便说下立即调用IIFE(Immediately Invoked Function Expression):
(function(){...})() 和 (function(){...}()) 是没区别的!
传统的定义函数为:
1 function foo(){...} //这是定义,Declaration,只是让解释器知道其存在,不会运行 2 3 foo(); //这是语句,解释器遇到语句会运行它
为什么要IIFE呢? 1:传统的方法啰嗦。 2:传统的方法污染全局命名空间
于是 我们这么写 function foo(){...}(); 这样写行么。。不行,为啥,因为function foo(){...}这部分只是声明,对解释器来说,像是你写了串字符串“function foo(){...}”,它需要的是解析函数,可以用比如eval()来执行它才可以。所以把()直接放声明后边是不行的,错误语法!
然而,我们距离成功相当接近,只需要把函数声明变成函数表达式就可以了。方法非常多,最常见的方法是用一对() 包裹起来。 (function foo(){...})();
这就等价于
1 var foo= function(){...}; 2 foo();
当然 还有很多别的方法可以把声明变成表达式:
1 !function foo(){...}(); 2 +function foo(){...}(); 3 void function() {...}();
需要全局对象的时候,可以这么传, 举例:
1 void function(global){ 2 console.log("a's value is: "+global.aa); //可以获取全局对象中aa的值 3 }(this)
1 var aa=10; 2 (function(a){ 3 console.log("hello world"+a); 4 })(aa);