Могу ли я обойти необязательные параметры и по-прежнему установить параметр отдыха в Javascript? - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть функция с обязательным параметром (A), некоторыми необязательными параметрами (B, C) и параметром отдыха (Z)

const doTheThing = (a, b = 'B', c = 'C', ...z) => {
  console.log(a, b, c, z);
}

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

doTheThing('A', ...'Z');

Ожидаемый результат:

'A', 'B', 'C', 'Z'

К сожалению, я получаю следующее:

Parsing error: Shorthand property assignments are valid only in destructuring patterns

Как мне решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

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

Простой JavaScript-подход: объект конфигурации как параметр

Вместо принятия нескольких параметров

func = (a, b, c) => { /* operate with parameters */ } 
func("One", "Two", "Three")

ваша функция вместо этого примет объект

func = config => { /* operate with config */ }
func({a: "One", b: "Two", c: "Three"})

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

const doTheThing = (config) => {
  const defaultProperties = { 
    b: "B", 
    c: "C"
  }
  
  const {a, b, c, ...rest} = Object.assign({}, defaultProperties, config);
  const z = Object.values(rest); //extract their values, otherwise you get an object
  
  console.log(a, b, c, z);
}

doTheThing({a: "A", x: "X", y: "Y", z: "Z"});

Немного неуклюже использовать с параметрами покоя, но не бесполезно.

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

Объектно-ориентированный подход: шаблон Builder

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

Это то, как больше объектно-ориентированных языков обрабатывают множество параметров, и некоторые из них могут быть необязательными. На самом деле не так часто встречаются такие конструкторы, определенные в JavaScript, но это не так уж странно. Если вы уже используете классы или даже TypeScript, то это, вероятно, лучше подходит.

class DoTheThingBuilder {
  constructor() {
    this.a = null;
    this.b = "B";
    this.c = "C";
    this.z = null;
  }
  
  withA(a) {
    this.a = a;
    
    return this;
  }
  
  withB(b) {
    this.b = b;
    
    return this;
  }
  
  withC(c) {
    this.c = c;
    
    return this;
  }
  
  withEverythingElse(...z) {
    this.z = z;
    
    return this;
  }
  
  doTheActualThing() {
    const {a, b, c, z} = this;
    console.log(a, b, c, z);
  }
}

const builder = new DoTheThingBuilder();

builder
  .withA("A")
  .withEverythingElse("X", "Y", "Z")
  .doTheActualThing();

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

Я немного отклонился от обычного подхода - обычно вы устанавливаете все параметры, необходимые для компоновщика, и, наконец, вызываете .build(), который создает объект . В этом случае я в основном переименовал build в doTheActualThing, и он выполняет функцию.

Функциональный подход: карри

Концепция каррирования довольно проста - вместо одной функции, принимающей несколько параметров

func = (a, b, c) => { /* operate with parameters */ }

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

func = a => b => c => { /* operate with parameters */ }

Во многих отношениях это функциональный эквивалент шаблона OO Builder.

const doTheThing = (a) => 
                   (b = "B") => 
                   (c = 'C') => 
                   (...z) => console.log(a, b, c, z);

doTheThing("A")()()("X", "Y", "Z");

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

0 голосов
/ 08 ноября 2018

Это невозможно и очень подвержено ошибкам. Смысл именования ваших параметров заключается в том, чтобы знать, что они из себя представляют и в каком порядке.

Вы можете достичь чего-то подобного, используя объект в качестве параметра функции:

const doTheThing = ({ a, b = "B", c = "C", others = {} }) => {
  const params = { a, b, c, ...others }; // this will merge your parameters into one object
  console.log(params);
}

doTheThing({ a: "A", others: { z: "Z" }});

Это будет лог A, B, C, Z. Демо: https://codepen.io/tomekbuszewski/pen/jQqmNL?editors=0011

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...