lastuniverse
@lastuniverse
Всегда вокруг да около IT тем

Использование операторов rest/spread и деструктуризации при передачи параметров в функцию?

Зачастую, при необходимости передать функции большое количество параметров, удобно использовать JSON/объект/ассоциативный массив.
пример
function anyFunc(options){
  // тут что то делаем обращаясь к параметрам через options.keyName.
  // например:
  const text = anyFormat(options.data, options.format);
  anySave(options.path+"/"+options.file, text);
}

anyFunc({
  path: "./temp",
  file: "plt_data.txt",
  data: [...],
  format: {
    fixed: 2,
    space: "  ",
    showLog: true,
    hideTitle: true		
  }
});


Все замечательно до тех пор, пока не окажется, что часть параметров должна иметь значения по умолчанию. В качестве решения для данного случая предлагается использовать Деструктурирующее присваивание с указанием значений по умолчанию. Но это, в свою очередь при некоторой вложенности передаваемого объекта и необходимости передать дополненные значениями по умолчанию параметры в следующую функцию создает некоторые неудобства.
пример
function anyFunc(options){
  // производим деструктуризацию
  const {
    path = "./temp",
    file = "plt_data.txt",
    data,
    format: {
      fixed = 2,
      space = "  ",
      showLog = false,
      hideTitle = false
    }
  } = options;
  // тут что то делаем обращаясь к параметрам уже по имени, не через keyName.
  // например:
  const text = anyFormat(data, {
    fixed: fixed,
    space: space,
    showLog: showLog,
    hideTitle: hideTitle
  }); // вот и новая проблема. Приходится собирать заново объект options.format
  anySave(path+"/"+file, text);
}

// при вызове функции теперь не обязательно указывать все параметры. Для пропущенных будут взяты значения по умолчанию.
anyFunc({
  data: [...],
  format: {
    showLog: true,
  }
});


Для обхода данной ситуации пришел к такому решению, с использованием rest и деструктуризации:
пример
// гдето в коде заданы значения по умолчанию (у меня в файле с конфигами, но это сейчас не важно))
const defaultOptions = {
  path: "./temp",
  file: "plt_temp_data.txt",
  format: {
    fixed: 2,
    space: "  ",
    showLog: false,
    hideTitle: false	
  }
};


function anyFunc(options){
  // производим деструктуризацию и rest для объектов с параметрами
  const { path, file, data, format } = options = {
     ...defaultOptions,
     ...options,
     format: {
       ...defaultOptions.format,
       space: ";  ",
       ...(options||{}).format
     }     
  };
  // тут что то делаем обращаясь к параметрам уже по имени, не через keyName.
  // например:
  const text = anyFormat(data, format);
  anySave(path+"/"+file, text);
}

// при вызове функции теперь не обязательно указывать все параметры. Для пропущенных будут взяты значения по умолчанию.
anyFunc({
  data: [...],
  format: {
    showLog: true,
  }
});


И данный вариант в принципе реализует задуманное, но мне все же как то не очень нравится такой синтаксис
const { path, file, data, format } = options = {
     ...defaultOptions,
     ...options,
     format: {
       ...defaultOptions.format,
       space: ";  ",
       ...(options||{}).format
     }     
  };


А в особенности эта строчка ...(options||{}).format (на нее даже sublimetext ругается)

Собственно суть вопроса: Подскажите более красивые/компактные/правильные и желательно нативные для JS способы добиться желаемого?
  • Вопрос задан
  • 135 просмотров
Решения вопроса 2
@dimoff66
Кратко о себе: Я есть
const { path, file, data } = Object.assign(options, defaultOptions, options)
const format = Object.assign({space: '; '}, defaultOptions.format, options.format)


Также можно подключить библиотеку lodash И использовать функцию merge
https://lodash.com/docs/4.17.11#merge

UPD Если предпочитаете деструктуризацию и не нравится упомянутый код, то вместо
options||{}

в параметрах функции сделайте значение по умолчанию
anyFunc(options = {}){
Ответ написан
dollar
@dollar
Делай добро и бросай его в воду.
//В лоб проще и короче. Ещё и умную валидацию можно прикрутить при желании
function anyFunc(options){
  // тут что то делаем обращаясь к параметрам через options.keyName.
  // например:
  const text = anyFormat(options.data, options.format || {});
  anySave((options.path||"./temp") + "/" + (options.file||"plt_temp_data.txt"), text);
}

//Аналогично
function anyFormat(data, format) {
  // ...... (format.fixed || 2) ........ (format.space || "  ") ...... и т.п.
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы