Skip to content

Instantly share code, notes, and snippets.

@rwaldron
Forked from ericf/gist:3751340
Created September 19, 2012 18:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • 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"
@rauschma
Copy link

Nice. I’d create an extra function that does the reducing. And you could additionally use this example to demonstrate parameter default values:

function foo({ file: null }) { ... }

@cjohansen
Copy link

I'm curious about the name. I had to read the description to understand what was being assigned. Why not go with something like "merge" or "extend" - names that have already been used in the wild for the same concept?

@rwaldron
Copy link
Author

Because it's not merging and "extend" has meaning:

// class constructors allow for real subclassing of built-ins...

class SubArray extends Array {
}

var myarray = new SubArray( 4, 8, 15, 16, 23, 42 );

myarray;

[ 4, 8, 15, 16, 23, 42 ];

"assign" is what it does... there is a strawman for a "define", which is the easier to swallow Object.defineProperties, and "merge" is essentially meaningless with regard to either of those concepts.

@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