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");
Таким образом, вы можете пропустить второй и третий параметр, не предоставляя их, и вы получите значения по умолчанию. Это также намного короче, чем строитель. Однако чтение функции может быть немного странным.