是否有可能"深度扩展"使用解构来设置传递给函数的对象的默认属性时的对象吗?
示例:
function foo({
foo = 'foo',
bar = 'bar',
baz = {
propA: 'propA',
propB: 'propB'
}
} = {}) {
console.log(foo);
console.log(bar);
console.log(baz);
}
foo({
foo: 'changed',
baz: {
propA: 'changed'
}
});

这输出:(巴兹被覆盖)
changed
bar
{
"propA": "changed"
}
是否存在扩展baz
对象的语法,以提供输出:
changed
bar
{
"propA": "changed",
"propB": "propB"
}
答案 0 :(得分:5)
没有本地方式可以按照您的要求进行操作,但您可以编写自己的function decorator
,当然这是一种冗长的方法......
注意:为了执行深度合并,您应该使用社区开发的一些现有解决方案,Object.assign
和Object Spread Operator
执行浅层副本即使是编写自己的deepmerge函数也可能容易出错。我建议您使用常见的lodash#merge
作为最佳解决方案。
var {
// https://lodash.com/docs/#merge
merge
} = require('lodash');
function defaultsArgDecorator(defaults, target) {
return function(args) {
return target(
merge(Object.create(defaults), args)
)
}
}
function _foo(args) { console.log({args}); }
var foo = defaultsArgDecorator({
foo: 'foo',
bar: 'bar',
baz: {
propA: 'propA',
propB: 'propB'
}
}, _foo);
foo({bar: "ciao bello", baz: {propA: "HELLO"}})
答案 1 :(得分:4)
由于参数解构允许您在其他参数的默认值中使用先前的参数,因此您可以创建一个不会退出原始参数的属性,例如__baz
,并使用{{1}设置其默认值}}。
在该方法中,您将使用baz
代替__baz
。
注意:这是一个hack,如果该对象包含一个属性 名称
baz
它将覆盖默认值,并带有意外结果。 但是,您可以使用类似名称来命名默认属性__baz
,使用率很低。
使用Object#assign
的默认属性:
dontUse__baz
使用object spread的默认属性(需要babel插件 - see link):
function foo({
foo = 'foo',
bar = 'bar',
baz,
__baz = Object.assign({
"propA": "changed",
"propB": "propB"
}, baz)
} = {}) {
console.log(foo);
console.log(bar);
console.log(__baz);
}
foo({
foo: 'changed',
baz: {
propA: 'changed'
}
});
答案 2 :(得分:0)
您也可以进行嵌套解构。你构造了baz,但也解构了propA
和propB
。
如果您需要整个对象并且不想重建'它,这不适合你,但它确实实现了一个目标,即为嵌套在对象中的未指定属性设置默认值。
我已经将baz
作为单独的descructured值除了它的属性之外作为一个有时方便的模式的示例,但你很可能想要删除它,因为它患有失去默认属性的同样问题。
function foo({
foo = 'foo',
bar = 'bar',
baz, // likely extraneous and confusing, here for example
baz: { propA = 'propA', propB = 'propB' }
} = {}) {
console.log(foo);
console.log(bar);
console.log(propA, propB);
console.log(baz);
console.log(Object.assign(baz, {propA, propB}));
}
foo({
foo: 'changed',
baz: {
propA: 'changed'
}
});