1、函數javascript
函數聲明、函數表達式、匿名函數java
函數聲明:使用function關鍵字聲明一個函數,再指定一個函數名,叫函數聲明。function name () { … }閉包
函數表達式:使用function關鍵字聲明一個函數,但未給函數命名,最後將匿名函數賦予一個變量,叫函數表達式。var name = function(){ ... }函數
匿名函數:使用function關鍵字聲明一個函數,但未給函數命名,因此叫匿名函數。function () { ... }spa
調用時的區別code
name(); //正常,由於‘提高'了函數聲明,函數調用可在函數聲明以前
function name(){ ... } name(); //報錯,變量name還未保存對函數的引用,函數調用必須在函數表達式以後
var name=function(){ ... }
函數參數傳遞方式:按值傳遞對象
咱們知道,函數的參數在進入函數後,實際是被保存在了函數的變量對象中,所以,這個時候至關於發生了一次複製。blog
var a = 20; function fn(a) { a = a + 10; return a; } fn(a); console.log(a); // 20 var a = { m: 10, n: 20 } function fn(a) { a.m = 20; return a; } fn(a); console.log(a); // { m: 20, n: 20 }
函數參數傳遞方式是按值傳遞,只不過當咱們指望傳遞一個引用類型時,真正傳遞的,只是這個引用類型保存在變量對象中的引用而已。token
2、當即執行函數ip
兩種javascript當即執行函數的常見寫法。
(function(){ … })() //(...)()形式 (function(){ … }()) //(...())形式
在函數的後面加上括號,就能變成當即執行函數嗎?
1.函數表達式後面加括號
var name=function(){ alert('Hello World'); }(); //函數表達式。後面加括號,當javascript引擎解析到此處時能當即調用函數
2.匿名函數後面加括號
function(){ console.log('Hello World'); }(); //匿名函數方式。後面加括號,報語法錯誤。雖然匿名函數屬於函數表達式,可是未進行賦值操做,因此javascript引擎將開頭的function關鍵字當作函數聲明,報錯:要求須要一個函數名。
3.函數聲明方式後面加括號
function name(){ alert('Hello World'); }(); //函數聲明方式,此時至關於對匿名函數加了名字。後面加括號,仍是報錯,Uncaught SyntaxError: Unexpected token )。在一個表達式後面加上括號(),該表達式會當即執行,可是在一個語句後面加上括號(),它的意思只是分組操做符。
function name(){
alert('Hello World');
}(1); //若是在括弧()裏傳入一個表達式,將不會有異常拋出.可是函數依然不會執行。由於它徹底等價於,在一個function聲明後面,又聲明瞭一個毫無關係的表達式
回頭看看( function(){…} )()和( function (){…} () ),要在函數體後面加括號就能當即調用,則這個函數必須是函數表達式,不能是函數聲明。
因此只須要用大括弧將代碼括住就好了,由於JavaScript裏括弧()裏面不能包含語句,因此在這一點上,解析器在解析function關鍵字的時候,會將相應的代碼解析成function表達式,而不是function聲明。
(function(a){ console.log(a); //123 })(123); //後面括號裏傳入了函數執行的參數。若是這個參數是外部的變量,將會造成閉包。這個變量也會保存在這個函數中。
3、模塊
提到當即執行函數,總會想到模塊,由於模塊一般用當即執行函數的方式去建立。
一個模塊能夠包括:私有變量、私有方法、公有變量、公有方法。
(function() { // 私有變量 var age = 20; var name = 'Tom'; // 私有方法 function getName() { return `your name is ` + name; } // 公有方法 function getAge() { return age; } // 將公有方法引用保存在外部執行環境的變量中,造成閉包,防止該執行環境被垃圾回收 window.getAge = getAge; })();