关闭 - 改变硬币

时间:2017-07-26 10:13:37

标签: javascript closures

我想了解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  ])();

我真的很感激任何帮助,解释和建议,阅读和练习更好地理解Closure。 我看到了类似Coins问题的解决方案,但我不想只使用它,我需要了解我在代码中做错了什么。

1 个答案:

答案 0 :(得分:2)

您在sortCoins内返回一个函数,这有点奇怪,因为您还在res内返回sortCoins

此外,您尚未定义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]));

结束它:

我们将创建一组硬币,如下所示:

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]);

现在myCoins_smallcoins属性设置为另一个不同的数组并返回另一个函数。现在,您有两个函数myCoinsmyCoins_small,每个函数都在其自己的上下文中运行,该函数设置了2个不同的coins属性。

简而言之。 JS中的闭包受功能限制。当您告诉代码对变量执行某些操作时,它将查看当前上下文(这是自己的函数)。如果找不到变量,将上升一级(也就是说,将查看父函数)并查看那里,如果在那里找不到它,将会上升到另一个级别,并且等等,直到达到所谓的全球范围&#34; (换句话说,第一行代码运行的主要级别。)

在这里你可以更容易地看到它:

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)调用两者来返回相同的输出。他们有微小的差异,但不会进入细节,不会弄得更多。