函數
在JavaScript中,函數也是一種資料類型,定義函數有兩種方式:
function f(){return 1;}var f=function(){return 1;}
所以,JavaScript中的函數是一種資料,但是它有兩個重要的特性: 包含的是代碼 是可執行檔
函數的命名規則和一般變數相同,不能以數字開頭、可以由任意的字母、數字、底線組成 匿名函數
一段資料既沒有賦值給某個變數,也沒有被賦予任何名字就是匿名的。匿名函數的兩種用法:
- 將匿名函數作為參數傳遞給其他函數,接收方函數就可以利用傳遞過來的匿名函數完成相應的任務
- 定義某個匿名函數來執行一些一次性任務 回呼函數
定義一個以兩個函數為參數的函數,該函數會分別執行這兩個參數函數:
//定義一個以兩個函數為參數的函數,該函數會分別執行這兩個參數函數,並返回它們的傳回值之和function invoke_and_add(a,b){ return a() + b();}//簡單定義參與運算的函數function one(){ return 1;}function two(){ return 2;}//將這兩個函數傳遞給目標函數invoke_and_add(one ,two);
在這裡我們可以用匿名函數來代替上面參與運算的兩個函數,作為目標函數的參數:
function invoke_and_add(a,b){ return a() + b();}invoke_and_add(function(){return 1;},function(){return 2;})
當我們將函數A傳遞給函數B,並且由B來執行A時,A就成了一個回呼函數(callback functions),如果此時A還是一個無名函數,那麼就叫它匿名回呼函數。 回呼函數的優勢 在不做命名的情況下傳遞函數,這也就是說可以節省全域變數 將一個函數調用委託給另一個函數,節省編碼 可以提高效能 回調樣本
一般將一個函數的傳回值傳遞給另一個函數。
//通過一個迴圈將其所接收的三個參數分別乘以2,並以數組的形式返回結果function multiplyByTwo(a,b,c){ var i,ar =[]; for(i=0;i<3;i++){ ar[i] = arguments[i]*2;} return ar;}//只接受一個參數,將它加1後並返回function addOne(a){ return a+1;}multiplyByTwo(1,2,3);addOne(100);
接下來,我們實現這三個元素在兩個函數之間的傳遞,在這定義一個用於儲存元素的數組,先從multiplyByTwo()的調用開始
var myarr = [];//定義一個數組myarr = multiplyByTwo(10,20,30);//調用函數
然後,用遍曆迴圈每個元素,並將它們分別傳遞給addOne()
for(var i=0;i<3;i++){ myarr[i] = addOne(myarr[i]) }myarr
在以上的過程中,使用了兩個迴圈,這是可以改進的將他們合二為一,對multiplyByTwo()函數改為接收一個回呼函數,並在每次迭代操作中調用它:
function multiplyByTwo(a,b,c,callback){ var i,ar =[]; for(i=0;i<3;i++){ ar[i] = callback(arguments[i]*2); } return ar;}function addOne(a){ return a+1;}myarr = multiplyByTwo(1,2,3,addOne);
我們還可以用匿名函數來代替addOne(),這樣可以節省一個額外的全域變數
function multiplyByTwo(a,b,c,callback){ var i,ar =[]; for(i=0;i<3;i++){ ar[i] = callback(arguments[i]*2); } return ar;}myarr = multiplyByTwo(1,2,3,function(a){return a+1});
自調函數
匿名函數的另一個應用,可以在定義後自行調用。
( function(){ alert('boo'); })()
只需要將匿名函數的定義放進一堆括弧中,然後外面再緊跟一對括弧即可,第二個括弧的作用是“立即調用”的意思,同時也是向匿名函數傳遞參數的地方。
( function(name){ alert('Hello '+ name +'!'); })('dudu')
內部私人函數
在一個函數內部定義另一個函數。
function a(param){ function b(theinput){ return theinput*2; }; return 'the result is ' + b(param);};
或者用函數標識記法:
var a = function(param){ var b = function(theinput){ return theinput*2; }; return 'the result is '+ b(param);};
當我們調用全域函數a()時沒,本地函數b()也會再其內部被調用,由於b()是本地函數,它在a()以外的地方是不可見的,所以稱它為私人函數。它的優勢有: 有助於確保全域名字空間的純淨性(就是命名衝突的幾率小) 私人性——可以選擇只將一些必要的函數暴露給外部,並保留屬於自己的函數,使得它們不能被程式的其他部分所用 返回函數的函數
函數始終都會有一個傳回值,即便不是顯式返回也會隱式返回一個undefined。既然函數能返回一個唯一的值,那麼這個值也有可能是另一個函數:
function a(){ alert('A!'); return function(){ alert('B!'); };}
函數a()會在執行說A之後返回另一個函數b(),而b()又會去執行另外一些事情說B,我們吧該傳回值賦值給某個變數,然後就可以向向使用一般函數一樣調用它了。
function a(){ alert('A!'); return function(){ alert('B!'); };}var newFunc = a();newFunc()
如執行結果所示,第一行執行的是A,第二行是B,若是想讓返回的函數立即執行,也可以不用將它賦值給變數,直接在該調用函數再加一對括弧就可以:
a()()
重寫自己的函數
一個函數可以返回另一個函數,因此可以用新的函數來覆蓋舊的函數,比如上個例子,可以通過a()的傳回值來重寫a()函數自己。
a = a();
當前這句依然只會執行alert(”A!”),但是我們再次調用a(),就會執行alert(“B!”)了。我們也可以讓函數從內部重寫自己:
function a(){ alert('A!'); a=function(){ alert('B!'); };}
一個綜合執行個體:
var a = function(){ function someSetup(){ var setup = 'done'; } function actualWork(){ alert('Worky-worky'); } someSetup(); return actualWork;}();
在這個函數中使用了私人函數:someSetup()和actualWork()
使用了自調函數:函數a()的定義後面有一對括弧,會執行自行調用。
當該函數第一次被調用時,會調用someSetup()函數,並返回函數變數actualWork的引用,注意傳回值是不帶括弧的,因此這個結果僅僅是一個函數的引用,並沒有執行函數不會產生函數調用。這裡執行的語句是以var a = 開頭的,因而該自調函數所返回的值會重新賦值給a