JS函数通过对象传递使用参数除下述两种方案外还有哪些可选方式?
可选实现方案
以下是几种不同场景下适用的实现方式:
1. Object.assign 合并默认配置
提前定义统一的默认配置对象,调用函数时用Object.assign将传入的配置和默认配置合并,不需要单独处理每个参数的默认值,适合配置项较多、默认值需要统一维护的场景。
// 提前定义全局通用默认配置 const DEFAULT_TIMER_CONFIG = { period: 1000, funStart: () => {}, funEnd: () => {}, funStartArguments: [], funEndArguments: [], warming: 0 } let timerClosure = function (timerConfigObj) { // 合并配置:传入的配置会覆盖默认值,未传的参数自动复用默认配置 const config = Object.assign({}, DEFAULT_TIMER_CONFIG, timerConfigObj) const { period, funStart, funEnd, funStartArguments, funEndArguments, warming } = config // 后续业务逻辑 }
2. 可选链 + 空值合并运算符取值
优化原方案2的逻辑,解决了||运算符会把0、false等合法假值当做空值覆盖的问题,更适合参数允许传入假值的场景。
let timerClosure = function (timerConfigObj) { let period = timerConfigObj?.period let funStart = timerConfigObj?.funStart ?? (() => {}) let funEnd = timerConfigObj?.funEnd ?? (() => {}) let funStartArguments = timerConfigObj?.funStartArguments ?? [] let funEndArguments = timerConfigObj?.funEndArguments ?? [] let warming = timerConfigObj?.warming ?? 0 // 后续业务逻辑 }
3. Proxy 代理配置对象
适合需要对配置参数做动态校验、访问拦截、自动类型转换等复杂需求的场景,不需要在函数内写大量零散的校验逻辑。
const createConfigProxy = (rawConfig) => { const DEFAULT = { period: 1000, funStart: () => {}, funEnd: () => {}, funStartArguments: [], funEndArguments: [], warming: 0 } return new Proxy(rawConfig ?? {}, { get(target, prop) { // 取值时优先取传入值,没有的话返回默认值,可自定义校验规则 const val = Reflect.get(target, prop) ?? DEFAULT[prop] // 示例:校验period必须为正整数 if (prop === 'period' && (typeof val !== 'number' || val < 0)) { throw new TypeError('period必须为正数字类型') } return val } }) } let timerClosure = function (timerConfigObj) { const config = createConfigProxy(timerConfigObj) // 直接取config.period就会自动返回处理后的值,非法值会直接抛出错误 // 后续业务逻辑 }
4. 类实例化配置
适合大型项目中配置需要多处复用、需要内置相关工具方法的场景,把配置和相关逻辑封装到类里,复用性和可维护性更强。
class TimerConfig { constructor(rawConfig = {}) { this.period = rawConfig.period ?? 1000 this.funStart = rawConfig.funStart ?? (() => {}) this.funEnd = rawConfig.funEnd ?? (() => {}) this.funStartArguments = rawConfig.funStartArguments ?? [] this.funEndArguments = rawConfig.funEndArguments ?? [] this.warming = rawConfig.warming ?? 0 // 构造函数里可以统一加校验逻辑 if (typeof this.period !== 'number' || this.period < 0) { throw new Error('period参数不合法') } } // 还可以内置相关工具方法,简化后续调用 runFunStart() { return this.funStart(...this.funStartArguments) } } let timerClosure = function (timerConfigObj) { const config = new TimerConfig(timerConfigObj) // 直接调用config.runFunStart()就可以执行对应方法 // 后续业务逻辑 }
内容的提问来源于stack exchange,提问作者Illusion
相关产品推荐
相关产品推荐

