为什么“回归”没有打破我的循环?

时间:2014-01-16 05:10:13

标签: javascript

这是我试图通过的测试:

describe("occur", function() {
  var getVal = function(i) { return i; };
  var even = function(num) { return num % 2 === 0; };

  it("should handle an empty set", function() {
    expect(occur([], getVal) ).toEqual(true);
  });

  it("should handle a set that contains only true values", function() {
    expect(occur([true, true, false], getVal)).toEqual(false);
  });

  it("should handle a set that contains one false value", function() {
    expect(occur([true, true, true], getVal)).toEqual(true);
  });

  it("should handle a set that contains even numbers", function() {
    expect(occur([0, 8, 32], even)).toEqual(true);
  });

  it("should handle a set that contains an odd number", function() {
    expect(occur([0, 13, 68], even)).toEqual(false);
  });
});

这是我的代码:

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

var occur = function(array, blah){
  forEach(array, function(el){
    if(!blah(el)){
      return false;
    }
  });
    return true;  
};

我相信我在发生的功能中所做的事情:

  1. 参数(数组和函数
  2. 迭代数组(在forEach中)
  3. 如果blah(el)不为true,则返回false(如果传入的函数计算为false,则不应该打破循环并返回false?
  4. 如果没有任何错误值,则返回true
  5. **我目前没有为空数组实现的案例。
  6. 我是否错过了返回工作的诀窍?我在下面提供了一个repl.it会话(链接)。我在if语句中包含了一个console.log,当值为false时它会记录'false',但返回值仍然没有输出或打破循环。

    http://repl.it/NjH/1

3 个答案:

答案 0 :(得分:1)

forEach在Javascript中未返回值 - 当您返回false时,您只是从false的回调中返回forEach。该值被忽略。

相反,如果您使用的是Node / Webkit等支持ECMAScript 5的兼容实现,则可以尝试Array.every()

否则,在forEach之外设置一个信号量变量,如果blah(el)返回false,则将其设置为false。然后在forEach完成后检查变量的值。

答案 1 :(得分:1)

你不会错过关于return的伎俩,你遗漏了关于.forEach的伎俩。

对于每个基本上看起来像这样:

function forEach (action) {
    var arr = this,
        i = 0, l = arr.length;

    for (; i < l; i += 1) {
        action(arr[i], i, arr);
    }
}

除此之外还有更多,但实际上,这就是它正在做的事情。

因此,如果action()中包含return语句(即使它没有,它只返回undefined,那么它与循环无关。< / p>

它表示“forEach”,它会让你得到的是一个遍历数组中的每一个项目(在调用函数时存在)。

答案 2 :(得分:1)

核心问题是return 总是退出最近的封闭函数 - 而不是其他。

var occur = function(array, blah){ // <-- "outer" function
  forEach(array, function(el){ // <-- callback to forEach / "enclosing" function
    if(!blah(el)){
      // This returns from the callback/enclosing function; it has no
      // bearing on the outer function.
      return false;
    }
  });
  return true;  
};

除非改变方法,否则可以使用变量解决此问题。

var occur = function(array, blah){
  var ret = true;
  forEach(array, function(el){
    if(!blah(el)){
      // Set the closed-over variable to false, so that when the return
      // in the outer function is reached the correct value will be returned.
      // (forEach will still iterate over every remaining item)
      ret = false;
    }
  });
  return ret;  
};

现在,我的建议是使用Array.some之类的东西(在ES5.1中,在IE9 +和每个现代浏览器中都支持)。

var occur = function(array, blah){
  var any = array.some(function(el){
    if(!blah(el)){
      return true;
    }
  });
  return !any;
};

但实际上,改变条件(内部/外部的否定以及someevery):

var occur = function(array, blah){
  return array.every(function(el){
    return blah(el);
  });
};