如何实现带默认属性且支持覆盖的函数对象参数?
函数参数默认对象的属性覆盖实现问题
我希望实现这样的函数:以带有默认属性的对象作为参数,调用函数时若传入包含部分属性的对象,传入的属性值会覆盖对应默认值;未传入的属性则保留默认值。请问是否可以通过如下示例1的写法实现该效果?还是必须像示例2那样手动逐个检查参数属性并设置默认值?
示例1
function foo( args={'param1':'val1', 'param2':'val2', 'param3':'val3'} ){ console.log(args) } foo() // 期望输出: {'param1':'val1', 'param2':'val2', 'param3':'val3'} foo({'param2':'newValue'}) // 期望输出: {'param1':'val1', 'param2':'newValue', 'param3':'val3'}
示例2
function foo( args={} ){ if( !args.param1 ){ args.param1 = 'val1' } if( !args.param2 ){ args.param2 = 'val2' } if( !args.param3 ){ args.param3 = 'val3' } console.log(args) }
回答
示例1的写法无法实现需求:JavaScript中函数参数的默认值仅在调用时未传入该参数(或传入
undefined)时生效。如果调用时传入了任意对象(哪怕只有部分属性),这个传入的对象会直接替换掉默认参数对象,不会自动合并属性。比如调用foo({'param2':'newValue'})时,args就是这个仅含param2的对象,不会包含默认的param1和param3。示例2的写法可行,但存在缺陷:逐个判断的方式能补上未传入的属性,但如果属性本身是
false、0、''这类假值时,会被错误覆盖。比如传入{'param1': ''},因为!args.param1为真,函数会把param1强制设为'val1',这不符合传入空值的预期。更优的实现方式:使用ES6+的对象展开语法合并默认值与传入参数,既简洁又能规避示例2的问题:
function foo(args = {}) { const defaultArgs = { param1: 'val1', param2: 'val2', param3: 'val3' }; const mergedArgs = { ...defaultArgs, ...args }; console.log(mergedArgs); } foo() // 输出: {param1: 'val1', param2: 'val2', param3: 'val3'} foo({param2: 'newValue'}) // 输出: {param1: 'val1', param2: 'newValue', param3: 'val3'} foo({param1: ''}) // 输出: {param1: '', param2: 'val2', param3: 'val3'},不会错误覆盖假值属性
这种方式会用传入对象的属性覆盖默认对象的对应属性,未传入的属性则保留默认值,同时能正确处理假值属性的场景。
内容的提问来源于stack exchange,提问作者Dani Pardo
相关产品推荐
相关产品推荐

