2013-02-15 67 views
0

我試圖瞭解從書中雄辯JavaScript本實用的風格代碼:的JavaScript:匿名VS輔助功能

http://eloquentjavascript.net/chapter6.html#exercise1

當count()函數傳遞一個匿名函數來減少()的代碼作品。但是如果我把這個函數分解成一個輔助函數,那麼我會得到一個引用錯誤。

任何人都可以解釋爲什麼計數()的作品,但countHelper()不?

var numbers = [1,2,3,0,1,2,3,0] 

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

function reduce(combine, base, array) { 
    forEach(array, function (element) { 
    base = combine(base, element); 
    }); 
    return base; 
} 

function equals(x) { 
    return function(element) { return x === element;}; 
} 

function count(test, array) { 
    return reduce(function(base, element) { 
    return base + (test(element)?1:0); 
    }, 0, array); 
} 

function countHelper(test, array) { 
    function helper(base, element) { 
    return base + (test(element)?1:0); 
    } 
    return reduce(helper(base, element), 0, array); 
} 

function countZeroes(array) { 
    return count(equals(0), array); 
} 

print(countZeroes(numbers)) // 2 

function countZeroesHelper(array) { 
    return countHelper(equals(0), array); 
} 

print(countZeroesHelper(numbers)) // ReferenceError: base is not defined 

回答

5

countHelper(),你實際上是立即調用輔助函數,當您將參數傳遞給reduce(),並通過其返回值減少(這是不是你想要的),而不是傳遞一個參考功能,所以reduce()可以在需要時調用該函數。你有這樣的:

function countHelper(test, array) { 
    function helper(base, element) { 
    return base + (test(element)?1:0); 
    } 
    return reduce(helper(base, element), 0, array); 
} 

它應該是這樣的:

function countHelper(test, array) { 
    function helper(base, element) { 
    return base + (test(element)?1:0); 
    } 
    return reduce(helper, 0, array); 
} 

注意,在參數給reduce()功能的差異。

當你想傳遞一個函數作爲參數時,你不會在它之後包含parens,因爲這會導致它立即執行並傳遞返回值來執行它,而不僅僅是傳遞一個引用給功能本身。

這是一種常見的錯誤,像JavaScript這樣的非類型語言,可以讓你在任何參數中傳遞任何東西。即使經驗豐富的程序員偶爾也會犯這個錯誤(包括我自己)。要理解的重要區別在於執行函數與傳遞函數引用之間的區別。