Skip to content

Instantly share code, notes, and snippets.

@rwaldron
Forked from ericf/gist:3751340
Created September 19, 2012 18:43
Show Gist options
  • Save rwaldron/3751415 to your computer and use it in GitHub Desktop.
Save rwaldron/3751415 to your computer and use it in GitHub Desktop.
ES6 Object.assign( target, source ) as a native options object merging pattern.
let defaults = { file: null };
function foo(options) {
// Merging defaults and options objects in ES6
options = [ defaults, options ].reduce(Object.assign, {});
}
foo({ file: "happy.md" });
/*
Object.assign( target, source )
When passed as the callback to reduce, the params are bound as:
function( prev, value ) {}
*/

Object.assign( target, source )

Object.assign( target, source )

Rough spec expectations:

  • Only enumerable own properties of source
  • Invoke [[Get]] on property list derived from source, for each property in list [[Put]] on target
  • private names are not copied
  • unique names are copied
  • super mechanism (rebind super)… AWB To determine needs
  • Returns modified "target"
@csnover
Copy link

csnover commented Dec 8, 2012

I really feel like if this function doesn’t accept more than one source object argument, people are going to keep writing alternatives for it so it might as well not even be in the spec. Using Array.prototype.reduce just doesn’t cut it when it comes to the sort of expressibility people have come to expect from jQuery.extend, dojo.mixin, etc.

@jdalton
Copy link

jdalton commented Dec 15, 2012

I've implemented _.extend and _.defaults to follow Object.assign and iterate only own properties in Lo-Dash v0.10.0+. The only real issue I've seen is in @tbranyen's backbone.layoutmanager which had to implement a custom augment method to normalize the behavior of Underscore/Lo-Dash because there was code that passed objects with inherited properties to _.extend.

Btw +1 on allowing multiple sources (_.extend and _.defaults allow it too).

@robotlolita
Copy link

I agree that Object.assign should be variadic. It makes not that much sense being non-variadic and forcing the users to jump through hoops to compose basic use cases when it could easily maintain the composition properties it already has and cover those use cases by just allowing multiple sources.

Why? It's easier to follow for static arguments (and doesn't mess with ASI!):

Object.assign({}, default, options)

// vs.

[ default, options ].reduce(Object.assign, {})

It can cover non-static arguments through both the familiar .apply and the Array::reduce:

Object.assign.apply(null, [{}].concat(xs))

// vs

xs.reduce(Object.assign, {})

On another note, I do find assign to have strong associations with replacing values and working with a single key/value association. I don't think define describes the operation being carried out that well either, but right now I can't think of any better names =/

@killroy42
Copy link

killroy42 commented Jul 24, 2016

Wouldn't this make more sense: (I might be late to this discussion)
constructor({opt1, opt2, opt3} = {opt1: def1, opt2: def2, opt3: def3}) { ... }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment