我有一个名为“Time”的函数,它接受 0 到 6 个参数。
function Time(year,month,day,hour,minutes,options) {
}
如果没有定义前一个参数,则无法定义月、日、时、分参数。
即使“options”参数是可选的,如果存在,它也必须是最后一个参数。
但是,用户只能定义年份和月份,然后是选项。
如何避免用户必须这样写:
var newTimeInstance = Time(2024,06, undefined, undefined, undefined, options {
fr: {
// ...
},
es: {
// ...
}
})
如果不可能,是否有其他方法将选项连接到函数?
我已经尝试过:
var newTimeInstance = Time(2024,01).options({ ... })
但是我无法访问newTimeInstance中的其他构造函数。
不方便,但你可以这样做:
function Time(...args) {
if (args.length === 3) {
const [year, month, options] = args
console.log({
year,
month,
options
})
}
// other cases
}
Time(2024, 4, {
extra: 'options'
})
使用
Array::reduceRight()
检查arguments
:
function Time(year,month,day,hour,minutes,options) {
[...arguments].reduceRight((r, arg, idx, arr) => {
if(arg === undefined && arr[idx + 1] !== undefined) throw new Error('An argument cannot be undefined');
});
}
Time(2024, 3, undefined); // ok
Time(undefined, 2); // an error
如何使用一种由 utiliy/helper 函数覆盖的自定义参数解析方法,其中一个附加的,在更详细的范围内,将决定参数签名是否有效以及是否清理某些值或抛出错误......
function isObjectObject(value) {
return (/^\[object\s+Object\]$/).test(
Object.prototype.toString.call(value)
);
}
function parseArgumentsSignature(args) {
const params = [];
let options;
let error;
args
.slice(0, 6)
// every allows an early exit while using a callback function.
.every((value, idx) => {
let proceed = true;
if (isObjectObject(value)) {
options = value;
proceed = false;
} else if (value == null) {
params[idx] = undefined;
} else {
value = parseInt(value, 10);
if (Number.isFinite(value)) {
params[idx] = value;
} else {
error = new TypeError('Invalid arguments signature.');
proceed = false;
}
}
return proceed;
});
return (error && {
error,
} || {
params,
...(options && { options } || {}),
});
}
function Time(...args/* year, month, day, hour, minutes, options */) {
const parsed = parseArgumentsSignature(args);
if (Object.hasOwn(parsed, 'error')) {
throw parsed.error;
}
const {
params: [
year = 0, month = 0, day = 0, hour = 0, minutes = 0,
],
options = null,
} =
parsed;
console.log({
year, month, day, hour, minutes, options, params: parsed.params,
});
}
console.log(
"Time(...[2024, 06,,, null, null, { fr: 'fr', es: 'es' }]);"
);
Time(...[2024, 06,,, null, null, { fr: 'fr', es: 'es' }]);
console.log(
"Time(...[2024, 06,,,, { fr: 'fr', es: 'es' }]);"
);
Time(...[2024, 06,,,, { fr: 'fr', es: 'es' }]);
console.log(
"Time(2024, { fr: 'fr', es: 'es' });"
);
Time(2024, { fr: 'fr', es: 'es' });
console.log(
"Time(2024, 06);"
);
Time(2024, 06);
console.log(
"Time(2024, 'foo bar');"
);
Time(2024, 'foo bar');
.as-console-wrapper { min-height: 100%!important; top: 0; }
为具有默认空值的参数创建一个对象(
{param1, param2, ..., paramx} = {}
,又名解构分配)。
这样你就永远拥有命名变量。调用函数需要更多的输入,但它提供了更好的(命名)参数处理, 灵活性(例如,您可以添加参数而无需破坏/不必重构对函数的现有调用),用户只需提供所需的参数,不需要以固定的顺序提供它们。
看起来像:
function Time({year,month,day,hour,minutes,options = `dst:0`} = {}) {
console.log(`your input: ${year ? `year: ${year}` : ``}${
month ? `, month: ${month}` : ``}${
day ? `, day: ${day}` : ``}${
hour ? `, hour: ${hour}` : ``}${
minutes ? `, minutes: ${minutes}` : ``} (options: ${options})`);
}
Time();
Time({year: 2024, hour: 12, options: `dst:1`});
Time(`this is not available`);
Time({year: 2024, month: 0, day: 21, hour: 12, minutes: 30,});
const now = new Date();
const params = {
year: now.getFullYear(),
month: now.getMonth(),
day: now.getDate(),
hour: now.getHours(),
minutes: now.getMinutes(),
options: `dst:1`
};
Time(params);
.as-console-wrapper {
max-height: 100% !important;
}