【问题标题】:Struggling with function factory & closure与功能工厂和关闭作斗争
【发布时间】:2018-03-09 15:00:49
【问题描述】:

很久之后,我又玩了一遍纯 JS。我正在努力解决关闭问题。

任务:我正在使用函数工厂为返回的函数设置参数,然后我想调用该函数。

问题:据我了解,参数是通过引用传递的,当执行上下文从堆栈中弹出时,变量会导致未定义的内存空间。我怎样才能做到这一点?

    function changeColorConstructor(greenLimit, redLimit) {
        var greenLimit = greenLimit;
        var redLimit = redLimit;
        console.log('1. Green Limit in Constructor shell: ' + greenLimit);
        
        return function(metric) {
          var color;
    
          console.log('3. Green Limit in returned function: ' + greenLimit);
    
          switch(metric) {
            case metric >= greenLimit:
              console.log('Green');
              color = '#56C621'; // green
              break;
            case metric < greenLimit && metric > redLimit:
              console.log('Yellow');
              color = '#F2E607'; // yellow
              break;
            case metric <= redLimit:
              console.log('Red');
              color = '#C64C20'; // red
              break;
            default:
              color = '#C0C0C0'
              break;
          }
          return color;
        }
    
      }
    
      var indexColor = changeColorConstructor(5000, 10000);
      console.log('2. Returned function: ' + indexColor);
    
      console.log('4. Output from production function: ' + indexColor(5000));

【问题讨论】:

  • 你的开关盒在我看来不合适...
  • "变量导致未定义的内存空间" - 不,这不是 JavaScript 的工作方式。描述您的实际问题,而不是您认为的问题。
  • 为什么要创建与传入参数同名的局部变量?
  • 我认为您在将函数/对象分配给 indexColor 时缺少 /new/ 关键字 --- var indexColor = new changeColorConstructor(5000, 10000); --- 否则,indexColor 是对函数的引用,而不是它自己的东西。
  • @Doug 不,indexColor 将是 changeColorConstructor 返回的函数,这很好(以及 OP 正在尝试做的事情)。这是一个函数发生器。

标签: javascript function scope closures


【解决方案1】:

据我所知,您的问题不在于闭包或函数工厂,而在于switch

switch(metric) {
    case metric >= greenLimit:

此代码将metricmetric &gt;= greenLimit 的结果进行比较,即它的工作方式类似于if (metric == (metric &gt;= greenLimit))

metric &gt;= greenLimittruefalse,因此将其与 metric 进行比较没有多大意义。

在下面的 sn-p 中,我已将您的 switch 语句替换为您想要的 if / else 级联,并删除了无意义的 var greenLimit = greenLimit; 分配。

function changeColorConstructor(greenLimit, redLimit) {
    console.log('1. Green Limit in Constructor shell: ' + greenLimit);

    return function (metric) {
        var color;

        console.log('3. Green Limit in returned function: ' + greenLimit);

        if (metric >= greenLimit) {
            console.log('Green');
            color = '#56C621'; // green
        } else if (metric < greenLimit && metric > redLimit) {
            console.log('Yellow');
            color = '#F2E607'; // yellow
        } else if (metric <= redLimit) {
            console.log('Red');
            color = '#C64C20'; // red
        } else {
            color = '#C0C0C0'
        }
        return color;
    };
}

var indexColor = changeColorConstructor(5000, 10000);
console.log('2. Returned function: ' + indexColor);

console.log('4. Output from production function: ' + indexColor(5000));

【讨论】:

    【解决方案2】:

    当我使用此 switch-case 技巧时,我能够打印出“绿色”:Switch on ranges of integers in JavaScript

    基本上,将要测试的开关设置为布尔值“true”以比较案例中的范围。

        function changeColorConstructor(greenLimit, redLimit) {
            var greenLimit = greenLimit;
            var redLimit = redLimit;
            console.log('1. Green Limit in Constructor shell: ' + greenLimit);
            
            return function(metric) {
              var color;
        
              console.log('3. Green Limit in returned function: ' + greenLimit);
        
              switch(true) {
                case metric >= greenLimit:
                  console.log('Green');
                  color = '#56C621'; // green
                  break;
                case metric < greenLimit && metric > redLimit:
                  console.log('Yellow');
                  color = '#F2E607'; // yellow
                  break;
                case metric <= redLimit:
                  console.log('Red');
                  color = '#C64C20'; // red
                  break;
                default:
                  color = '#C0C0C0'
                  break;
              }
              return color;
            }
        
          }
        
          var indexColor = changeColorConstructor(5000, 10000);
          console.log('2. Returned function: ' + indexColor);
        
          console.log('4. Output from production function: ' + indexColor(5000));

    【讨论】:

    • 这个解决方案的问题是它很脆弱,并且让人们非常容易地认为他们可以重新排序案例、更改值而不考虑执行顺序等。正如链接问题的几个 cmets 中所讨论的那样,这对于 switch 不是一个很好的用途。
    • @DaveNewton 我同意 - 很高兴看到在 switch-cases 中解决范围挑战的工作,但我喜欢 melpomene 的解决方案,将其转换为一系列 if-else 语句。
    • 你是对的,在这种情况下,使用 if/else 的解决方案比破解 switch 语句更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-17
    • 2015-04-23
    • 1970-01-01
    • 2012-02-26
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多