将对象作为函数参数进行深度扩展

时间:2016-12-05 11:42:37

标签: javascript ecmascript-6

是否有可能"深度扩展"使用解构来设置传递给函数的对象的默认属性时的对象吗?

示例:



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"
}

3 个答案:

答案 0 :(得分:5)

没有本地方式可以按照您的要求进行操作,但您可以编写自己的function decorator,当然这是一种冗长的方法......

注意:为了执行深度合并,您应该使用社区开发的一些现有解决方案,Object.assignObject 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,但也解构了propApropB

如果您需要整个对象并且不想重建'它,这不适合你,但它确实实现了一个目标,即为嵌套在对象中的未指定属性设置默认值。

我已经将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'
  }
});