Обычно всё вручную делают:
function Foo(name, options) {
this.name = name || 'default name';
options = options || {};
this.x = options.x || 100;
this.y = options.y || 200;
this.text = options.text || 'default value';
this.fill = options.fill || 'default value';
}
Но надо быть осторожнее с
||. Это применимо только тогда, когда передаваемые параметры предполагаются не равными
false (с двойным равно). Т.е. если
x может принимать нулевое значение, то надо будет делать уже так:
if (typeof params.x !== 'undefined') {
this.x = params.x;
} else {
this.x = 100; // значение по-умолчанию
}
Ну или использовать тренарный оператор, как уже написали.
UPD
Поясню логику. В js нет опциональных параметров. Однако, если функция объявлена с одним количеством аргументов, а вызывают её с меньшим, то ошибки не возникнет, а все незаполненные параметры становятся равными undefined внутри контекста функции. И, чтобы заполнить их какими-то данными по-умолчанию, используют логическое или - ||. Далее, имеется выражение:
foo|| bar
. Если foo будет соответствовать лжи, то выражение вернёт второй операнд. Если foo соответствует истине, то вернёт первый (в силу ленивости оператора). Тут есть тонкий момент. undefined соответствует лжи. Однако, если функия допускает значения foo, которые могут соответствовать лжи (null, false, {}, [], ''), то это выражение не будет работать правильно. Об этом надо помнить и обрабатывать такие случаи с помощью
(if typeof foo === 'undefined') ? 'default value' : foo;
.
Ну и естественно, это выражение применимо и в обычных функциях (собственно, функция-конструктор и обычная функция ничем не отличаются, их отличает лишь использование, а именно - ключевое слово
new). В таком случае пишут так:
function foo(x, y, z) {
x = x || 1;
y = y || 'y';
z = z || true;
// После такой "инициализации" идёт код, использующий эти переменные.
}
Ну и в твоём примере точно таким же способом проверяются поля переданного объекта: если поле не передано в функцию, то при вызове его из объекта оно вернёт значение undefined.