2012-09-01 48 views
3

我在使用總和函數時遇到了困難,該函數調用了Eloquent Javascript (Chapter 6)的匿名函數代碼示例,但我明白在這個post上澄清了什麼,我真的不明白匿名函數被調用。在Eloquent Javascript中解釋匿名函數代碼示例第6章

從我明白這個代碼:

function forEach(array, action) { 
    for (var i = 0; i < array.length; i++) 
    action(array[i]); 
} 

function sum(numbers) { 
    var total = 0; 
    forEach(numbers, function (number) { 
    total += number; 
    }); 
    return total; 
} 
alert(sum([1, 10, 100, 1000])); 

與此類似代碼(感謝來自@CKKiller在其他線程的援助):

numbers = [1, 10, 100, 1000]; 
for (var i = 0; i < numbers.length; i++) { 
    var number = numbers[i]; 

    function (number) { 
    total += number; 
    } 
} 
alert(total); 

但我不能運行第二個代碼示例,它有什麼問題?根據我的理解,不可能調用語法函數(number){},但不是第一個示例指示函數執行什麼操作?

回答

3

在第二個代碼片段中,您只是聲明瞭一個匿名函數。 撥打吧,它應該可以正常工作。 「立即調用函數表達式」,你應該這樣做:

(function(){ 
    // Your code 
})(); 

或者

(function(){ 
    // Your code 
}()); 

他們被稱爲IIFE的。 (在上面引用中)

正如user1600680在下面的評論中指出的那樣,要編輯您的代碼,您必須從參數列表中刪除number。它想是這樣的:

(function() { 
    total += number; 
})(); 
+0

或者如果你感覺很勇敢,你可以做'new function(){}' – Eric

+1

Sho我們需要指出的是,問題中顯示的'number'參數需要刪除,因爲它會影響'number'變量,否則需要將'number'作爲參數傳遞給IIFE。 –

1

第二個例子並不調用匿名函數,它只是聲明函數。因此,for循環對total變量沒有任何作用(我假設它在之前的某個地方被聲明過)。 alert(total)只會輸出上次分配給總數的內容(因爲匿名函數永遠不會被調用,total不會被更新)。

+0

第二個示例不聲明該函數。這是無效的語法,'alert'永遠不會發生。 –

+0

至少它運行在犀牛中,用'print'替換'alert',並在具有初始值的代碼之前的某個位置聲明'total'(並且'print'輸出這個初始值) – LeleDumbo

2

但是我不能運行第二個代碼示例,它有什麼問題?

你有函數聲明沒有名字:

function (number) { 
    total += number; 
} 

函數聲明總是必須包括函數的名稱。在說明書中參見section 13

從我的理解是不可能的調用語法function (number) {},而這不正是第一個例子是指示功能呢?

不是這樣。在第一個例子中,你有一個函數表達式,因爲該函數是在表達式上下文中定義的(它作爲參數傳遞給其他函數)。函數表達式不需要名稱。表達式被計算爲一個函數對象,然後作爲參數傳遞給forEachfunction (number) {}不調用該函數,它定義它。

我真的不明白匿名函數是如何調用

沒有什麼特別的地方。重要的方面是函數是第一類對象,即它們可以分配給變量並像其他任何值(原始值或對象)一樣傳遞給其他函數。 action指的是一個函數,所以你可以用action()來調用該函數。該功能直接傳遞給forEach

forEach(numbers, function (number) { 
    // ... 
}); 

雖然它被稱爲內forEach,它可以更新的total的價值,因爲它是sum定義,因此它可以訪問所有的本地變量關閉裏面sum

你可能還定義事先功能:

function sum(numbers) { 
    var total = 0; 
    function add(number) { 
     total += number; 
    } 
    forEach(numbers, add); 
    return total; 
} 

但是如果你使用一個值只有一次,那麼就沒有必要將它分配給一個變量第一(或宣佈爲此事功能) 。例如,也直接傳遞數組sum

sum([1, 10, 100, 1000]) 

代替第一它賦值給一個變量:

var numbers = [1, 10, 100, 1000]; 
sum(numbers); 

一種等同於第一代碼表示相似的行爲將是:

var numbers = [1, 10, 100, 1000], 
    total = 0, 
    action = function(number) { // variable assignment -> expression context 
     total += number; 
    }; 

for (var i = 0; i < numbers.length; i++) { 
    var number = numbers[i]; 
    action(number); 
} 

alert(total);