以前看了好多代码,都有用到这种函数的写法,可是都没认真的去想为何会这样写,今天开始想学习下jquery的源码,发现jquery也是使用这种方式,用(function(window, undefined){})(window)包裹内部代码,因而进一步的去学习了下。javascript
要理解当即执行函数(function(){})(),先了解些函数的基本概念(函数声明、函数表达式、匿名函数)。java
函数声明:使用function声明函数,并指定函数名。 jquery
function setFn() { // coding }
函数表达式:使用function声明函数,但未指定函数名,将匿名函数赋予一个变量。安全
var setFn = function() { // coding }
匿名函数:使用function关键字声明函数,但未指定函数名。匿名函数属于函数表达式,匿名函数有不少做用,赋予一个变量则建立函数,赋予一个事件则成为事件处理程序或建立闭包等等。闭包
function() { // coding }
函数声明与函数表达式的不一样在于:函数
1. 函数声明可在当前做用域下提早调用执行,函数表达式需等执行到该函数后,方可执行,不可提早调用。学习
setFn() function setFn() { // coding } // 正常,函数声明可提早调用 setFn() var setFn = function() { // coding } // 报错,setFn未保存对函数的引用,函数调用需放在函数表达式后面
2. 函数表达式可直接在函数后加括号调用。测试
var setFn = function() { console.log(2) }() // 2 解析至此,可直接执行调用
当即执行函数(function(){})()能够看出很像函数表达式的调用,但为何要加括号呢?若是不加括号:spa
function(){ console.log(1) }() // 报错,函数须要函数名
解析: 虽然匿名函数属于函数表达式,但未进行赋值,因此javascript解析时将开头的function当作函数声明,故报错提示须要函数名
当即执行函数里面的函数必须是函数表达式,因此由var setFn = function() {}()能够理解为在匿名函数前加了 = 运算符后,将函数声明转化为函数表达式,因此拿!,+,-,()...等运算符来测试下是否如此。code
!function(){ console.log(1) }() // 1 +function(){ console.log(2) }() // 2 -function(){ console.log(3) }() // 3 (function(){ console.log(4) })() // 4
因而可知,加运算符确实可将函数声明转化为函数表达式,而之因此使用括号,是由于括号相对其余运算符会更安全,能够减小没必要要的麻烦。
当即执行函数与正常函数传参形式是一致的。
(function(a, b){ console.log(a + b); })(1, 2) // 3
(function(){}())这样写的好处是在内部定义的变量不会跟外部的变量有冲突,达到保护内部变量的做用。