2014-01-16 106 views
0

這裏是我試圖通過測試:爲什麼不'返回'打破我的循環?

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)不爲真,則返回false(不應該在循環中打開循環並返回false,只要傳入的函數計算結果爲false?
  4. 如果沒有任何錯誤值,則返回true
  5. **我沒有目前爲空數組實施的情況。

我錯過了如何返回工作的訣竅?我在下面提供了一個repl.it會話(鏈接)。我在if語句中包含了一個console.log,當值爲false但是返回值仍然不輸出或中斷循環時,它會記錄'false'。

http://repl.it/NjH/1

+2

回報*永遠只*從*最近的封閉函數返回*。也就是說,在上面的代碼中對'forEach'的回調。 ('forEach'函數不會返回任何有用的東西,我會創建一個'any/some'或者一個'filter' - 這兩個都存在於ES5/5.1中 - 而是使用返回值。) – user2864740

+0

我認爲我對理解的問題並沒有完全圍繞「回調」功能進行。我不太確定'最近的封閉函數'是什麼意思。 '最近'是如何確定的? – HelloWorld

回答

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); 
    }); 
}; 
1

forEach當您返回false不返回Javascript--一個值,你只需從forEach的回調返回false。該值被忽略。

取而代之的是,你可以,如果你使用的是兼容的實現如Node/WebKit的/一些支持的ECMAScript 5

否則儘量Array.every(),設置forEach外的信號變量,如果blah(el)其設置爲false返回false。然後在forEach完成後檢查變量的值。

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,不要緊的循環可言。

它說「的forEach」和它所將讓你是一個合格遍歷數組中的每一個項目(即存在於函數被調用時)

+1

@ user2864740它不能解決返回問題。它突出了迴歸問題,回答「我是否錯過了回報工作的一個技巧」,因爲它是逐字地執行'.forEach',以詳細表明問題是什麼,學會捕魚,而不是去捕捉一個。更長的答案在此可以稍後提供。 – Norguard

+1

@ user2864740 Bah。你是對的 - 我的失敗是忽視了它不是原生的Array.prototype。 forEach',因此,我忽略了誤解的本質。使用'[] .forEach'而不理解循環/回調關係不是問題。我很抱歉;我會在下一次精神休息期間更新這個答案。 – Norguard