2

我有范围函数和输出函数它们工作正常,现在我想创建 sum 函数用作范围函数中的 callbac 函数,但是当某些函数执行局部变量时让我们说总或总和初始化 0(零),如何解决这个问题?

    function range(start,end,callback,step) {
        // body...
        step=step || 1;
        for(i=start;i<=end;i=i+step){
            callback(i);
        }
    }
    function output(a) {
        // body...
        console.log(a);
    }
    function sum(m){
       var total=0;
       // some code
}
    range(1,5,output);
    range(1,5,sum);
4

4 回答 4

1

延续风格的代码,就像你用 range() 开始的一样,会变得非常奇怪和麻烦。

请注意定义你的局部变量。喜欢i

function range(start,end,callback,step) {
  step=step || 1;
  for(var i=start; i<=end; i=i+step)
    callback(i);
}
    
function output(...label) {
  return function(...args){
    console.log(...label, ...args);
  }
}

function sum(callback){
  var total = 0;
  return function(value){
    //will log ever intermediate total, because sum() has no way to tell when the sequence is over.
    callback(total += +value || 0);
  }
}

range(1,5,output('range:'));
range(1,5,sum(output('sum:')));

在这种情况下,我更喜欢使用生成器,尽管高阶函数已经过时了。

function *range(start,end,step) {
  step = +step || (end < start? -1: 1);
  for(var value = start, count = (end - start) / step; count-- >= 0; value += step)
    yield value
}

function sum(iterator){
  var total = 0, v;
  for(v of iterator) total += +v || 0;
  return total;
}

console.log("range:", ...range(1,5))
console.log("sum of range:", sum(range(1,5)))

//just to show that this works with your regular array as well
console.log("sum of array:", sum([1,2,3,4,5])); 

//and some candy, as requested by Bergi ;)
//I like to stay with the interfaces as close as possible to the native ones
//in this case Array#reduce
var fold = (iterator, callback, start = undefined) => {
  var initialized = start !== undefined,
    acc = start,
    index = 0,
    value;
		
  for(value of iterator){
    acc = initialized?
      callback(acc, value, index):
      (initialized=true, value);
    ++index;
  }
  if(!initialized){
    throw new TypeError("fold of empty sequence with no initial value");
  }
  return acc;
}
//and the ability to compose utility-functions
fold.map = (callback, start = undefined) => iterator => fold(iterator, callback, start);

console.log(" ");

var add = (a,b) => a + b; //a little helper
console.log('using fold:', fold(range(1,5), add, 0));

//a composed utility-function
var sum2 = fold.map(add, 0);

console.log('sum2:', sum2( range(1,5) ));

于 2017-03-08T22:51:22.773 回答
1
 function range(start,end,callback,step) {
        // body...
        var aggregate;
        step=step || 1;
        for(i=start;i<=end;i=i+step){
            aggregate = callback(i, aggregate);
        }
    }
    function output(a) {
        // body...
        console.log(a);
    }
    function sum(m, aggregate){
       return m + aggregate;
    }
    range(1,5,output);
    range(1,5,sum);

这样你甚至可以做一些很酷的事情,比如

function conc(m, aggregate) {
    return aggregate + m.toString();
}

range(1,5,conc,2); //prints 135
于 2017-03-08T22:18:21.787 回答
0

显然,一个range函数不应该接受回调,而应该是现代 JavaScript 中的生成器函数,但是您问的是如何编写这样的回调。

你已经用closures标记了你的问题,它们确实是这里的方法。通过在外部函数的每次调用中初始化一个新total的,您无需担心如何重置全局计数器。

function makeSum() {
    var total=0;
    return function(m) {
        total += m;
        return total; // so that we can access the result
    }
}

var sum = makeSum();
range(1, 5, sum);
output(sum(0));
于 2017-03-08T23:37:22.413 回答
0

如果回调不是未定义的,那么简单地调用范围数组上的回调就足够了吗?像这样:

> function range(n, callback) {
    const r = [...Array(n).keys()]
    if (callback) {
      return callback(r)
    }
    return r
  }

> function sum(arr) {
    return arr.reduce((a, b) => a + b, 0)
  }

> range(10)

> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

> range(10, sum)

> 45
于 2017-03-08T23:37:32.933 回答