2017-07-26 73 views
0

我想了解Closure概念,因此練習此練習。但是我完全迷茫和困惑。任務是找到需要用來滿足總數的最小硬幣。結果是£7.60我想要一個數組 res = [2,2,2,1,0.5,0.1]關閉 - 更換硬幣

這裏是我到目前爲止有:

function sortCoins (money, coins){ 
    res = []; 

if(money % coins[0] !== 0){ 
    return function(){ 
    do{ 
     money = money - coins[0]; 
     res.push(coins[0]); 
    } 
    while(coins[0]<= money); 
    coins.shift(); 
    }; 
    // coins.shift(); 
} else { 
    do{ 
     money = money - coins[0]; 
     res.push(coins[0]); 
    } 
    while(money !== 0); 
} 

return res; 


} 

sortCoins (17, [5, 2, 1, 0.5, 0.25, 0.1 ])(); 

我會很感激的任何幫助,說明和建議讀什麼書和實踐,瞭解關閉更好。 我看到類似Coins問題的解決方案,但我不想只用它,我需要了解我在代碼中做錯了什麼。

+0

你能解釋一下你的代碼中沒有工作或應該改進的東西嗎? – T30

+0

@ T30感謝您的回覆。現在我的資源是不確定的,我想獲得資源= [5,5,5,2],因爲它是需要用來滿足17的最小硬幣。 – Polina

回答

2

您在sortCoins中返回一個函數,這有點奇怪,因爲您還在sortCoins中返回res

另外,您還沒有定義res變量,因爲您之前沒有添加var,所以訪問的是未定義的全局變量。

,最後一個,作爲小費,讓您的縮進乾淨。你有一堆空間,這使得代碼塊一見難見。

總之,問題是回報。讓我來解決這個問題:

功能:

function sortCoins(money, coins){ 
    var res = []; 
    // Use an index instead of modifying the array. Keep the parameters immutable when possible. 
    var current = 0; 
    do { 
     money = money - coins[current]; 
     res.push(coins[current]); 
     while (money < coins[current]) { 
      current++; 
     } 
    } while(money > 0); 
    return res; 
} 

// console.log it, to see in the F12 console tab 
console.log(sortCoins(17, [5, 2, 1, 0.5, 0.25, 0.1])); 

Closuring它:

我們要打造一個集幣,這樣的:

function sortCoins(coins) { 
    // Notice that this function returns another function 
    return function(money) { 
     var res = []; 
     // Use an index instead of modifying the array. Keep the parameters immutable when possible. 
     var current = 0; 
     do { 
      money = money - coins[current]; 
      res.push(coins[current]); 
      while (money < coins[current]) { 
       current++; 
      } 
     } while(money > 0); 
     return res; 
    }; 
} 

var myCoins = sortCoins([5, 2, 1, 0.5, 0.25, 0.1]); 
myCoins(17); 

var myCoins_small = sortCoins([0.5, 0.25, 0.1]); 
myCoins_small(17); 

myCoins(12); 
myCoins_small(12); 

看看sortCoins函數的內容。使用正確的縮進很容易看出它返回了一個函數。不看返回函數的內容,你可以看到這是它唯一的回報:

function sortCoins(coins) { 
    // Notice that this function returns another function 
    return function(money) { 
     [...] 
    }; 
} 

所以,如果你叫sortCoins([5, 2, 1, 0.5, 0.25, 0.1])它將返回在coins參數設置爲[5, 2, 1, 0.5, 0.25, 0.1]功能。

var myCoins = sortCoins([5, 2, 1, 0.5, 0.25, 0.1]); 

現在你有一個變量myCoins,這是一個功能,其中它的coins參數設置爲[5, 2, 1, 0.5, 0.25, 0.1]。換句話說,就像有這段代碼:

var coins = [5, 2, 1, 0.5, 0.25, 0.1]; 
function myCoins(money) { 
    var res = []; 
    // Use an index instead of modifying the array. Keep the parameters immutable when possible. 
    var current = 0; 
    do { 
     money = money - coins[current]; 
     res.push(coins[current]); 
     while (money < coins[current]) { 
      current++; 
     } 
    } while(money > 0); 
    return res; 
}; 

會發生什麼事,如果你調用myCoins(17);在這最後一段代碼?如果仔細觀察,它會訪問coins變量,因此如果將coins變量更改爲[0.5, 0.25, 0.1],您將收到不同的輸出。

你怎麼改變呢?讓我們再回到第一sortCoins(coins)功能,是與另一coins屬性打電話一樣容易:

var myCoins_small = sortCoins([0.5, 0.25, 0.1]); 

現在​​有coins屬性設置爲另一個不同的陣列,並返回另一個函數。現在你有2個函數,myCoins和​​,每個函數在其自己的上下文中運行,其中有兩個不同的coins屬性設置。

總之。 JS中的閉包受功能限制。當你告訴代碼對某個變量做某事時,它會查看當前的上下文(這是自己的函數)。如果沒有找到變量,就會上一層(也就是說,會查看父函數)並在那裏查找,如果沒有找到它,就會上升到另一個層次,直到達到所謂的「全局範圍」(換句話說,第一行代碼運行的主要級別)。

在這裏,你可以看到它更容易:

var mainlevel = 0; // This variable is declared in the global scope, so exists in ALL the functions 

function level1() { 
    var level1variable = 1; // This variable is declared inside level1 function, so exists in ALL the level1 function and its descendants 

    function level2() { 
     var level2variable = 2; // This variable is declared inside level2 function, so exists in ALL the level2 function and its descendants 

     // level2 has access to its own variables and the one in his parents 
     console.log(level2variable, level1variable, mainlevel); 
    } 

    // If I say level1 to access level2variable, it will return error as cannot access it 
    console.log(level2variable); 

    // But it can actually access his own variables and the parent ones 
    console.log(level1variable, mainlevel); 
} 

有了這一點,並知道JS保持返回的功能的情況下,你可以做真棒事情currying(這是我們與第一所作的事情sortCoins(coins)函數)。

如果你得到一個有點失落,注意

function pepe(arg) { 
    return arg * 2; 
} 

相同

var pepe = function(arg) { 
    return arg * 2; 
}; 

既可以與pepe(2)返回相同的輸出被調用。他們有微小的差異,但不打算進入細節不要把你的頭更多。

+0

非常感謝您的解釋和建議!但我注意到,如果我用sortCoins(11,[5,2,1,0.5,0.25,0.1])檢查代碼),結果將是錯誤的。而且它不再是關閉,這仍然是很好的練習,但我最好想理解在函數內返回函數的概念... – Polina

+0

@Polina更新了一個修復和詳細的答案 –

+0

非常感謝你這只是最好的解釋! – Polina