2013-02-15 63 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这样的非类型语言,可以让你在任何参数中传递任何东西。即使经验丰富的程序员偶尔也会犯这个错误(包括我自己)。要理解的重要区别在于执行函数与传递函数引用之间的区别。