【问题标题】:Generate chunks of code (functions, variables) from array (forEach)?从数组(forEach)生成代码块(函数、变量)?
【发布时间】:2017-01-16 13:38:28
【问题描述】:

我有这段代码:

foo.bar('run', function () {       
  var text1 = foo.url('./src/url/text1.txt')
          .go(bar.do({ something }))
          .also(bar({
              variable: 1,
              else: 2,
          }).on('exception', doSomething ))
          .also(bar.url('.src/url/source'))

  var textLong = foo.url('./src/url/textLong.txt')
          .go(bar.do({ something }))
          .also(bar({
              variable: 1,
              else: 2,
          }).on('exception', doSomething ))
          .also(bar.url('.src/url/source'))

  var text = foo.url('./src/url/text.txt')
          .go(bar.do({ something }))
          .also(bar({
              variable: 1,
              else: 2,
          }).on('exception', doSomething ))
          .also(bar.url('.src/url/source'))

  return myCustomFunction(text1, textLong, text);
}

您可以看到它尽可能地抗 DRY,每个变量都是相同的,除了变量名和文件名 (foo.url)。

我一直想知道是否有可能使它更简单,例如:

var files = [ 'text1', 'textLong', 'text'];

然后:

foo.bar('run', function () {    
  files.forEach(function(fileName){
        var fileName = foo.url('./src/url/'+ fileName + '.txt')
        .go(bar.do({ something }))
        .also(bar({
            variable: 1,
            else: 2,
        }).on('exception', doSomething ))
        .also(bar.url('.src/url/source'))
  })

  return myCustomFunction(text1, textLong, text);
})

但我可以通过第二种方法获得的最佳效果是text1 is not defined。 SO上有一些关于动态创建变量的问题,但它们通常具有相同的名称+我从未见过它们与自定义函数结合使用。

有什么提示吗?

【问题讨论】:

    标签: javascript loops foreach eval


    【解决方案1】:

    我已经用来自 Ates Gora、Thomas、Bergi 的提示更新了这个答案。

    使用 ES2016 中实现的一些功能,解决方案可能如下所示:

    foo.bar('run', function () {
    
      return myCustomFunction(
    
        ...[ 'text1', 'textLong', 'text' ].map(fileName => {
    
          return foo.url(`./src/url/${fileName}.txt`)
            .go(bar.do({ something }))
            .also(bar({
              variable: 1,
              else: 2,
            })
            .on('exception', doSomething ))
            .also(bar.url('.src/url/source'));
    
         });
    
      );
    
    });
    

    【讨论】:

    • 甚至:`./src/url/${fileName}.txt`
    • 另外,对于上面的字符串常量数组,使用const 而不是let
    • 应该是return myCustomFunction( ...resultOfFilesMap ); 而不是...files
    【解决方案2】:

    您可以使用.map() 收集对数组中的项目执行操作的结果,然后使用.apply() 使用一组可能的参数调用函数:

    foo.bar('run', function () {    
      var results = files.map(function(fileName){
        return foo.url('./src/url/'+ fileName + '.txt')
          .go(bar.do({ something }))
          .also(bar({
            variable: 1,
            else: 2,
          })
          .on('exception', doSomething ))
          .also(bar.url('.src/url/source'));
      });
    
      return myCustomFunction.apply(null, results);
    });
    

    【讨论】:

    • 您的解决方案会以某种方式改变我的文件顺序吗?因为它似乎正在工作,但 textLong.txt 在 text1.txt 中有一些依赖项,现在我收到“未定义变量”错误:((我一直在使用 foo/bar/txt 作为虚拟示例,事实上我'我在这里使用带有咖啡脚本文件的 Gulp)。谢谢!
    • 不,.map() 保留订单。
    • 我正在合并流(myCustomFunction 是“合并”IRL):npmjs.com/package/gulp-merge
    【解决方案3】:

    永远不要使用动态变量。您想改用数组:

    foo.bar('run', function () {    
        var files = [ 'text1', 'textLong', 'text'];
        var texts = files.map(function(fileName) {
    //                    ^^^ get back the results
            return foo.url('./src/url/'+ fileName + '.txt')
    //      ^^^^^^ don't assign to anything
            .go(bar.do({ something }))
            .also(bar({
                variable: 1,
                else: 2,
            }).on('exception', doSomething ))
            .also(bar.url('.src/url/source'))
      })
    
      return myCustomFunction(texts[0], texts[1], texts[2]);
    })
    

    【讨论】:

    • 它似乎工作得很好,但不知何故它破坏了加载这些文件的顺序,请参阅@Ates Goral 答案下的评论。不过感谢您的出色回答!
    • “有一些依赖关系”是什么意思?代码中没有关于这种事情的任何内容。我的答案与您的原始代码完全相同;当然,两者都可能涉及一些竞争条件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2015-02-16
    • 1970-01-01
    • 2011-07-18
    • 2017-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多