?
一、函數
函數聲明、函數表達式、匿名函數
函數聲明:使用function關鍵字聲明一個函數,再指定一個函數名,叫函數聲明。function name () { … }
函數表達式:使用function關鍵字聲明一個函數,但未給函數命名,最后將匿名函數賦予一個變量,叫函數表達式。var name = function(){ ... }
匿名函數:使用function關鍵字聲明一個函數,但未給函數命名,所以叫匿名函數。function () { ... }
?
調用時的區別
name(); //正常,因為‘提升'了函數聲明,函數調用可在函數聲明之前
function name(){ ... }name(); //報錯,變量name還未保存對函數的引用,函數調用必須在函數表達式之后
var name=function(){ ... }
?
函數參數傳遞方式:按值傳遞
我們知道,函數的參數在進入函數后,實際是被保存在了函數的變量對象中,因此,這個時候相當于發生了一次復制。
var a = 20; function fn(a) {a = a + 10;return a; } fn(a); console.log(a); // 20var a = { m: 10, n: 20 } function fn(a) {a.m = 20;return a; } fn(a); console.log(a); // { m: 20, n: 20 }
函數參數傳遞方式是按值傳遞,只不過當我們期望傳遞一個引用類型時,真正傳遞的,只是這個引用類型保存在變量對象中的引用而已。
?
?
二、立即執行函數
兩種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); //后面括號里傳入了函數執行的參數。如果這個參數是外部的變量,將會形成閉包。這個變量也會保存在這個函數中。
?
?
三、模塊
提到立即執行函數,總會想到模塊,因為模塊通常用立即執行函數的方式去創建。
一個模塊可以包括:私有變量、私有方法、公有變量、公有方法。
(function() {// 私有變量var age = 20;var name = 'Tom';// 私有方法function getName() {return `your name is ` + name;}// 公有方法function getAge() {return age;}// 將公有方法引用保存在外部執行環境的變量中,形成閉包,防止該執行環境被垃圾回收window.getAge = getAge; })();
?
?
?