从数组(forEach)生成代码块(函数,变量)?

时间:2017-01-16 13:38:29

标签: javascript loops foreach eval

我有这段代码:

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有一些问题,但它们通常具有相同的名称+我从未见过它们与自定义函数相结合。

任何提示?

3 个答案:

答案 0 :(得分: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);
});

答案 1 :(得分:2)

我已经用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'));

     });

  );

});

答案 2 :(得分:1)

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

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        ImageList = new ObservableCollection<ViewModel> { new ViewModel { ImageURI = "ms-appdata:///local/1.png" }, new ViewModel { ImageURI = "ms-appdata:///local/2.png" }, new ViewModel { ImageURI = "ms-appdata:///local/3.png" } };
    }

    public ObservableCollection<ViewModel> ImageList;

    private async void ListView_ItemClick(object sender, ItemClickEventArgs e)
    {
        FileOpenPicker openPicker = new FileOpenPicker();
        openPicker.ViewMode = PickerViewMode.Thumbnail;
        openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
        openPicker.FileTypeFilter.Add(".jpg");
        openPicker.FileTypeFilter.Add(".jpeg");
        openPicker.FileTypeFilter.Add(".png");

        StorageFile file = await openPicker.PickSingleFileAsync();

        if (file != null)
        {
            WriteableBitmap Bitmap = new WriteableBitmap(1, 1);
            using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
            {
                Bitmap.SetSource(stream);
            }

            var clickedItem = e.ClickedItem as ViewModel;

            var FileName = clickedItem.ImageURI.Replace("ms-appdata:///local/", string.Empty);

            await SaveToLocalStorage(FileName, Bitmap);

            clickedItem.NotifyPropertyChanged("ImageURI");
        }
    }

    public static async Task SaveToLocalStorage(string FileName, WriteableBitmap Bitmap)
    {
        StorageFile outputFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting);
        using (IRandomAccessStream writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
        {
            byte[] pixels;
            using (Stream stream = Bitmap.PixelBuffer.AsStream())
            {
                pixels = new byte[(uint)stream.Length];
                await stream.ReadAsync(pixels, 0, pixels.Length);
            }
            // Encode pixels into stream
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, writeStream);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, (uint)Bitmap.PixelWidth, (uint)Bitmap.PixelHeight, 96, 96, pixels);
            await encoder.FlushAsync();
        }
    }
}

public class ImageURIConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var image = new BitmapImage();

        using (IRandomAccessStream stream = (StorageFile.GetFileFromApplicationUriAsync(new Uri(value.ToString())).AsTask().Result).OpenAsync(FileAccessMode.Read).AsTask().Result)
            image.SetSource(stream);

        return image;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

public class ViewModel : INotifyPropertyChanged
{
    private string imageURI;

    public string ImageURI
    {
        get
        {
            return imageURI;
        }

        set
        {
            imageURI = value;
            NotifyPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}