Одна из самых важных книг о программировании и стилях программирования - это книга под названием «Чистый код». В этой книге есть важный совет, которому я всегда стараюсь следовать: Максимальное количество параметров функции должно быть 3, и вы всегда должны стараться использовать 2 или меньше. Сначала я не понимал, почему это было важно, но по мере того, как я продолжал писать тонны Javascript, меня это начало поражать.

Допустим, мы определяем следующую функцию и имеем шесть потенциальных значений параметров.

const addToInventory = function(itemName, category, brokerName, sellingCost, initialCost, inStock) {
// Some code goes here
};

С точки зрения определения функции это имеет смысл, поскольку у нас есть переменные для каждого параметра. Переменные названы очень хорошо, и они будут что-то значить в коде функции. Однако мы сталкиваемся с проблемой ясности при выполнении функции и с проблемой установки параметров по умолчанию. Вызов этой функции может выглядеть так

addToInventory("Awesome Thing", "Toys", "Chester McChester", 12, 6, false);

Если вы похожи на меня, то, если вы вернетесь к этому коду позже, вы будете ломать голову над тем, что означает каждое из этих значений. Что такое «12»? Кто такой «Честер Макчестер?» Почему передается случайное «ложное»?

Теперь предположим, что некоторые из этих параметров были необязательными, и мы могли бы вызвать функцию следующим образом

addToInventory("Awesome Thing", "Toys");

Неплохо с точки зрения ясности… но что произойдет, если вы захотите установить начальную стоимость? Вам нужно затем установить имя брокера и sellCost? Или ты мог бы просто сделать это

addToInventory("Awesome Thing", "Toys", undefined, undefined, 6);

Как будто установка значений параметров без контекста достаточно сбивает с толку, добавление случайных «неопределенных значений» просто добавляет дополнительный уровень «Что, здесь происходит?»

Оберните значения параметров в объект!

Давайте проведем рефакторинг `addToInventory` и вместо этого будем использовать объект для хранения всех наших параметров. Я собираюсь использовать деструктурирование, чтобы показать, как можно легко распаковать значения из объекта params. Если вы не использовали деструктуризацию, я предлагаю вам прочитать об этом на странице https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring.

const addToInventory = function(params) {
const {itemName, category, brokerName, sellingCost, initialCost, inStock} = params;
// Some code goes here
};

// Or you could you could destructure right 
// in the function parameter declaration
const addToInventory = function({itemName, category, brokerName, sellingCost, initialCost, inStock}) {
// Some code goes here
};

Теперь давайте посмотрим, как теперь будет выглядеть вызов этой функции.

const params = {
  itemName: "Awesome Thing",
  category: "Toys",
  brokerName: "Chester McChester",
  sellingCost: 12,
  initialCost: 6,
  inStock: false
};
addToInventory(params);
// And with optional values
const params = {
  itemName: "Awesome Thing",
  category: "Toys",
  initialCost: 6
};
addToInventory(params);

Бум. Теперь, когда я вернусь к этому коду позже, я буду примерно знать, что означает каждое из этих значений, поскольку для меня будет доступен ключ объекта. Я пойму, что «Awesome Thing» - это название предмета, а не какое-то другое случайное значение. Нам также не нужно устанавливать значения объектов в каком-либо конкретном порядке, и мы можем пропустить необязательные значения.

Итак, следующий вопрос, что вы будете делать со значениями по умолчанию?

Значения по умолчанию в ES6

В предыдущем примере я использовал деструктуризацию, так как у нее есть дополнительная особенность. Деструктуризация позволяет нам устанавливать значения по умолчанию для каждой переменной, которую мы извлекаем из параметров (вы можете узнать больше об этом на https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Default_values_2 ).

Давайте посмотрим, как мы можем установить значения по умолчанию с помощью деструктурирования.

const addToInventory = function(params) {
const {itemName = 'someName', brokerName, sellingCost, initialCost = 0, inStock = true} = params;
// Some code goes here
};

Используя эту технику, itemName по умолчанию будет иметь значение «someName», initialCost будет по умолчанию равно 0, а inStock по умолчанию будет иметь значение «true».

Использование значений по умолчанию для деструктуризации отлично подходит для объектов, но мы изначально заявили, что объекты не нужны при использовании одного или двух параметров. Как насчет установки значений по умолчанию, когда мы не используем объект?

Параметры ES6 по умолчанию

Я не мог написать сообщение о параметрах и не упомянуть параметры ES6 по умолчанию. Если у вас будет более трех параметров, вам, вероятно, следует использовать объект. Если нет, то вам следует проверить Параметры ES6 по умолчанию.

В прошлом программистам Javascript часто приходилось устанавливать такие значения по умолчанию

const myFunc1 = function(param1, param2) {
  if(param1 === undefined) {
    param1 = myDefault1;
  }
  if(param2 === undefined) {
    param2 = myDefault2;
  }
  // Some code goes here
};
// Or the more concise and risky
const myFunc2 = function(param1, param2) {
  param1 = param1 || myDefault1;
  param2 = param2 || myDefault2;
  // Some code goes here
};

Это часто раздражало разработчиков, поскольку в других языках были простые способы установки параметров по умолчанию. К счастью, ES6 добавил параметры по умолчанию, и теперь вы можете это сделать.

const myFunc = function(param1 = myDefault1, param2 = myDefault2) {
    // Some code goes here
};

Параметры по умолчанию помогают избавиться от утомительного программирования и помогают избежать пожара мусорной корзины по поводу ложных значений в Javascript.

Значения по умолчанию в ES5

Я хотел добавить быстрый раздел для тех, кто застрял в поддержке старых браузеров и не может использовать Babel.

Если вы еще не использовали Object.assign, я настоятельно рекомендую вам проверить его. В официальном отчете MDN говорится.

Метод Object.assign () используется для копирования значений всех перечислимых собственных свойств из одного или нескольких исходных объектов в целевой объект. Он вернет целевой объект.

Это тонкий, но мощный метод в том смысле, что вы можете легко объединять объекты, создавать клоны и устанавливать приоритет объектов в зависимости от порядка источников.

Давайте посмотрим, как могут выглядеть настройки по умолчанию с помощью нашей функции addToInventory.

const addToInventory = function(params) {
  params = Object.assign({
    itemName: "",
    category: "Other",
    brokerName: "General",
    sellingCost: 0,
    initialCost: 0,
    inStock: false
  }, params);
  
  const {itemName, category, brokerName, sellingCost, initialCost, inStock} = params;
  // Some code goes here
};

Теперь начальная «цель» установлена ​​со всеми желаемыми параметрами по умолчанию, а переданный объект params при необходимости перезаписывает значения по умолчанию. Если ваш объект по умолчанию находится вне функции (например, в глобальном объекте конфигурации), вы даже можете установить пустой объект в качестве цели и установить значения по умолчанию в качестве источника.

Обратите внимание, что цель будет изменена, поэтому вам не следует устанавливать глобальные объекты в качестве целевого параметра.

const addToInventory = function(params) {
  params = Object.assign({}, myDefaults, params);
  const {itemName, category, brokerName, sellingCost, initialCost, inStock} = params;
  // Some code goes here
};

Но что, если я хочу использовать все значения по умолчанию? Одна из замечательных особенностей Object.assign заключается в том, что он игнорирует неопределенные источники. Это означает, что в приведенной выше функции объект params может быть передан как «undefined», и Object.assign все равно будет работать нормально.

Резюме

По сути, вот что вы можете сделать, чтобы очистить параметры вашей функции и эффективно установить значения по умолчанию.

  • Сохраняйте количество параметров функции не более 3
  • Если вам нужно более 3 значений параметров, используйте объект
  • Если вы используете объект и можете использовать ES6, используйте деструктурирование, чтобы установить значения по умолчанию.
  • Если вы используете объект и не можете использовать ES6, используйте Object.assign, чтобы легко установить значения по умолчанию.
  • Если вы не используете объект в качестве параметра и можете использовать ES6, используйте параметры ES6 по умолчанию.
  • Если вы не используете объект в качестве параметра и не можете использовать ES6, вам просто нужно проверить, не определено ли значение.

Надеюсь это поможет!