<div dir="ltr">`Object.defineProperties(target, Object.getOwnPropertyDescriptors(source))`?</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Feb 13, 2020 at 2:24 AM Andrea Giammarchi <<a href="mailto:andrea.giammarchi@gmail.com">andrea.giammarchi@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Both `Object.assign` and `{...extend}` suffer a tiny gotcha: properties are never assigned, neither retrieved, as accessors, with side-effects too.</div><div><br></div><div>Example:<br></div><div>```js<br>const Counter = {<br>  _count: 0,<br>  get count() {<br>    return this._count++;<br>  }<br>};<br><br>const incr1 = Object.assign({}, Counter);<br>const incr2 = {...Counter};<br><br>console.log(<br>  incr1.count,    // 0<br>  incr2.count,    // 1<br>  Counter._count  // 2<br>);</div><div><br></div><div>// functionality also compromised<br></div><div>console.log(incr1.count === incr1.count);<br></div><div>```<br></div><div><br></div><div>Not only most of the time this is unexpected, but there's literally no way to pass along accessors with a similar `Object.assign` ease, even if that's what most developers would expect (at least up to the first time they encounter above issue).</div><div><br></div><div>How about we introduce `Object.assignProperties` instead?</div><div><br></div><div>A polyfill example:<br></div><div><br></div><div>```js</div><div>const {assign, defineProperties, getOwnPropertyDescriptors} = Object;<br>const assignProperties = (base, ...mixins) => defineProperties(<br>  base,<br>  mixins.reduce(<br>    (descriptors, mixin) => assign(<br>      descriptors,<br>      getOwnPropertyDescriptors(mixin)<br>    ),<br>    {}<br>  )<br>);<br></div><div>```</div><div><br></div><div>We can now use objects and mixins without side-effecting sources used to extend, and preserving accessors in the process.</div><div><br></div><div>```js<br>const Counter = {<br>  _count: 0,<br>  get count() {<br>    return this._count++;<br>  }<br>};<br><br>const incr1 = Object.assignProperties({}, Counter);<br>const incr2 = Object.assignProperties({}, Counter);<br><br>console.log(<br>  incr1.count,    // 0<br>  incr2.count,    // 0<br>  Counter._count  // 0<br>);<br><br>// always false: preserved functionality<br>console.log(incr1.count === incr1.count);</div><div>```<br></div><div><br></div><div>Thoughts ?<br></div></div>
_______________________________________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" rel="noreferrer" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
</blockquote></div>