[英]Destructuring objects as function parameters deep extend
在使用解構來設置傳遞給函數的對象的默認屬性時,是否可以“深度擴展”對象?
例:
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"
}
沒有本地方法可以做你所要求的,但你可以編寫自己的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"}})
由於參數解構允許您在其他參數的默認值中使用先前的參數,因此可以創建不在原始參數上退出的屬性,例如__baz
,並使用baz
設置其默認值。 在該方法中,您將使用__baz
而不是baz
。
注意:這是一個hack,如果對象包含名稱為
__baz
的屬性,它將覆蓋默認值,並帶有意外結果。 但是,您可以使用類似dontUse__baz
名稱來命名默認屬性,其使用的可能性非常低。
使用Object#assign
默認屬性:
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' } });
使用對象傳播的默認屬性(需要babel插件 - 請參閱鏈接 ):
function foo({ foo = 'foo', bar = 'bar', baz, __baz = { "propA": "changed", "propB": "propB", ...baz } } = {}) { console.log(foo); console.log(bar); console.log(__baz); } foo({ foo: 'changed', baz: { propA: 'changed' } });
您也可以進行嵌套解構。 你破壞了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' } });
是的,完全有可能!
解決方案1:
function foo({
foo = 'foo',
bar = 'bar',
baz: {
propA = 'propA',
propB = 'propB'
} = {}
}) {
console.log(foo)
console.log(bar)
console.log({propA, propB}) // Because `bar` is renamed to `{propA, propB}`. Hence, no local variable named `baz`
}
解決方案2(解決方法):
function foo({
foo = 'foo',
bar = 'bar',
baz = {}
}) {
// ...
const baz2 = Object.assign({}, {propA: 'propA', propB: 'propB'} = {})
console.log(baz2) // Yeah, not really a solution
}
你甚至可以這樣做:
const func = ([{foo, bar: {a, b: BB, c: CC = 'c'} = {}} = {}], ...{0: rest0 = 0, 1: rest1 = '1'}) => { /* do stuffs */ }
上面的代碼是一個復雜的例子,我將使用更簡單的例子來解釋:
例1:
const f1 = ({x: varx}) => console.log(varx)
當你調用f1(obj)
, obj.x
將被分配給f1
范圍內的varx
例2:
const f2 = ({xy: {x, y}}) => console.log({x, y})
與f1
類似,但用{x, y}
代替varx
, obj.xy
將分配給{x, y}
,因此x = obj.xy.x
和y = obj.xy.y
示例3:現在讓我們添加create default參數
const f3 = ({xy: {x, y} = {}}) => { /* do stuffs */ }
現在,您仍然必須將obj
作為對象傳遞,但您不再需要提供obj.xy
如果undefined
obj.xy
,則x
和y
undefined
示例4:現在,讓x
和y
具有默認值
const f4 = ({xy: {x = 'XXX', y = 'YYY'} = {}}) => { /* do stuffs */ }
如果你傳遞的obj.xy
undefined
, {x, y}
將被設置為{x: undefined, y: undefined}
,但由於x
和y
也有默認值, x
將為'XXX'
, y
將為'YYY'
例4:“終極生命形式”
const f5 = ({xy: {x = 'XXX', y = 'YYY'} = {}} = {}) => { /* do stuffs */ }
我猜我不必解釋這個:D
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.