Object.assign()
On Wednesday, October 17, 2012 at 10:27 PM, Axel Rauschmayer wrote:
I’m a bit skeptical about excluding non-enumerable properties for Object.assign(). I still find enumerability a hard concept to wrap my mind around, because it pops up in unexpected places. At the moment, it mostly matters for for...in and Object.keys()/Object.getOwnPropertyNames(). Does it really make sense to increase its role in JavaScript?
It's a matter of paving the cow path of least surprise. Imagine if you tried to copy the properties and values of a plain object to an object with a
On Wednesday, October 17, 2012 at 10:34 PM, Rick Waldron wrote:
On Wednesday, October 17, 2012 at 10:27 PM, Axel Rauschmayer wrote:
I’m a bit skeptical about excluding non-enumerable properties for Object.assign(). I still find enumerability a hard concept to wrap my mind around, because it pops up in unexpected places. At the moment, it mostly matters for for...in and Object.keys()/Object.getOwnPropertyNames(). Does it really make sense to increase its role in JavaScript?
Sorry about that, I accidentally hit send...
It's a matter of paving the cow path of least surprise. Imagine if you tried to copy the properties and values of a plain object to an object with a null prototype and all of those properties you explicitly didn't want were now present.
On Wednesday, October 17, 2012 at 10:27 PM, Axel Rauschmayer wrote:
I’m a bit skeptical about excluding non-enumerable properties for Object.assign(). I still find enumerability a hard concept to wrap my mind around, because it pops up in unexpected places. At the moment, it mostly matters for for...in and Object.keys()/Object.getOwnPropertyNames(). Does it really make sense to increase its role in JavaScript?
It's a matter of paving the cow path of least surprise. Imagine if you tried to copy the properties and values of a plain object to an object with a null prototype and all of those properties you explicitly didn't want were now present.
But those won’t be copied, because only own properties will be copied. I’d be more worried about adding non-enumerable own properties to an object and those not being copied.
Addendum: For example, you won’t be able to reliably use Object.assign() to mix an object with methods into a prototype object, because those methods might be non-enumerable.
I think I initially misunderstood you. You think that what I’ve mentioned above is a feature, I’d argue that it is a bug.
On Wednesday, October 17, 2012 at 10:47 PM, Axel Rauschmayer wrote:
On Wednesday, October 17, 2012 at 10:27 PM, Axel Rauschmayer wrote:
I’m a bit skeptical about excluding non-enumerable properties for Object.assign(). I still find enumerability a hard concept to wrap my mind around, because it pops up in unexpected places. At the moment, it mostly matters for for...in and Object.keys()/Object.getOwnPropertyNames(). Does it really make sense to increase its role in JavaScript?
It's a matter of paving the cow path of least surprise. Imagine if you tried to copy the properties and values of a plain object to an object with a null prototype and all of those properties you explicitly didn't want were now present. But those won’t be copied, because only own properties will be copied. I’d be more worried about adding non-enumerable own properties to an object and those not being copied.
I've always viewed enumerability as an implied intent of sharing. Copying non-enumerable properties is a violation of my expectations (I assure you, I'm not alone)
On Wednesday, October 17, 2012 at 10:53 PM, Axel Rauschmayer wrote:
Addendum: For example, you won’t be able to reliably use Object.assign() to mix an object with methods into a prototype object, because those methods might be non-enumerable.
This not a silver bullet by any means. If you define that object and all of those methods haven't been explicitly set to enumerable:false, then they will all copy
I've always viewed enumerability as an implied intent of sharing. Copying non-enumerable properties is a violation of my expectations (I assure you, I'm not alone)
That is an interesting point. Does the prevention of sharing ever occur in practice (apart from hiding the methods of built-in prototype objects from for...in)?
On Wednesday, October 17, 2012 at 11:18 PM, Axel Rauschmayer wrote:
I've always viewed enumerability as an implied intent of sharing. Copying non-enumerable properties is a violation of my expectations (I assure you, I'm not alone)
That is an interesting point. Does the prevention of sharing ever occur in practice (apart from hiding the methods of built-in prototype objects from for...in)?
In my experience, this is extraordinarily rare (so much that I can't think of any relevant code bases)
On Oct 17, 2012, at 8:32 PM, Rick Waldron wrote:
On Wednesday, October 17, 2012 at 11:18 PM, Axel Rauschmayer wrote:
I've always viewed enumerability as an implied intent of sharing. Copying non-enumerable properties is a violation of my expectations (I assure you, I'm not alone)
That is an interesting point. Does the prevention of sharing ever occur in practice (apart from hiding the methods of built-in prototype objects from for...in)?
In my experience, this is extraordinarily rare (so much that I can't think of any relevant code bases)
Pardon, I missed and cannot find what is Object.assign(...), seems it's not from the latest draft. Is it just defining properties (via Object.defineProperty) on from a source to destination object? Like old-good Object.extend(...)?
But from just an abstract viewpoint -- we could control non-enumerable properties with a boolean flag (includeNonEnumerable).
Dmitry
Pardon, I missed and cannot find what is Object.assign(...), seems it's not from the latest draft. Is it just defining properties (via Object.defineProperty) on from a source to destination object? Like old-good Object.extend(...)?
Explained here: rwldrn/tc39-notes/blob/master/es6/2012-09/sept-18.md
On Oct 17, 2012, at 9:34 PM, Axel Rauschmayer wrote:
Pardon, I missed and cannot find what is Object.assign(...), seems it's not from the latest draft. Is it just defining properties (via Object.defineProperty) on from a source to destination object? Like old-good Object.extend(...)?
Explained here: rwldrn/tc39-notes/blob/master/es6/2012-09/sept-18.md
I see, thanks.
So, from what I see:
- Source should not be the one. We should support many of sources to copy all them at once:
Object.assign(dest, source1[, source2, ... sourceN])
In addition:
- If the last parameter is boolean, then it's created as includeNonEnumerable:
Object.assign(desc, source1[, source2, ... sourceN, includeNonEnumerable);
Example;
Object.assign({a: 10}, {b: 20}, Object.defineProperties({}, {c: {value: 30}}), true); // {a: 10, b: 20, c: 30}
Dmitry
Rick Waldron wrote:
On Wednesday, October 17, 2012 at 10:47 PM, Axel Rauschmayer wrote:
On Wednesday, October 17, 2012 at 10:27 PM, Axel Rauschmayer wrote:
I’m a bit skeptical about excluding non-enumerable properties for Object.assign(). I still find enumerability a hard concept to wrap my mind around, because it pops up in unexpected places. At the moment, it mostly matters for for...in and Object.keys()/Object.getOwnPropertyNames(). Does it really make sense to increase its role in JavaScript?
It's a matter of paving the cow path of least surprise. Imagine if you tried to copy the properties and values of a plain object to an object with a null prototype and all of those properties you explicitly didn't want were now present.
But those won’t be copied, because only own properties will be copied. I’d be more worried about adding non-enumerable own properties to an object and those not being copied. I've always viewed enumerability as an implied intent of sharing. Copying non-enumerable properties is a violation of my expectations (I assure you, I'm not alone)
That's it. I was not able to phrase it this way, but I agree. That's why I was struck by making concise methods enumerable.
Axel Rauschmayer wrote:
Addendum: For example, you won’t be able to reliably use Object.assign() to mix an object with methods into a prototype object, because those methods might be non-enumerable.
That's wrong use of Object.assign. Remember the debate on :=, there is intent distinction between [[Put]] and [[DefineOwnProperty]]. And Object.assign, if I am not mistaken, does [[Put]]. For copying methods, you should do [[DefineOwnProperty]] (that is, Object.define, if it is there).
When exactly do you want to carte blanche copy everything off of a method-bearing object without doing some reconnaissance? I personally make heavy use of enumerability to make my intentions as a library author known, rather than using '_' prefixed properties. Partially because I have less need to worry about backward compatibility but also partially because i think because es5 hasn't quite disseminated into common use yet seemingly.
On Thu, Oct 18, 2012 at 12:59 AM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:
On Oct 17, 2012, at 9:34 PM, Axel Rauschmayer wrote:
Pardon, I missed and cannot find what is Object.assign(...), seems it's not from the latest draft. Is it just defining properties (via Object.defineProperty) on from a source to destination object? Like old-good Object.extend(...)?
Explained here: rwldrn/tc39-notes/blob/master/es6/2012-09/sept-18.md
I see, thanks.
So, from what I see:
- Source should not be the one. We should support many of sources to copy all them at once:
Object.assign(dest, source1[, source2, ... sourceN])
I had originally hoped for this, but we reached consensus on Object.assign(dest, source) to allow for a possible descriptor map param.
The pattern you're looking for can be achieved as....
[ defaults, options, overrides ].reduce(Object.assign, {});
In addition:
- If the last parameter is boolean, then it's created as includeNonEnumerable:
Object.assign(desc, source1[, source2, ... sourceN, includeNonEnumerable);
Boolean parameters are a non-starter and would conflict with the desire to have an optional third "default descriptor map" parameter.
The original proposal was for two methods: Object.assign and Object.define.
Object.assign would pave the cowpath of all of the extend() APIs already in circulation. We thought the precedent of not copying enumerable methods in those cases was enough reason for Object.assign to have this behavior.
We discussed Object.define for a while, but didn't feel like there was enough precedent either with a library function like Object.define or with Object.defineProperty in general to make a decision here. Instead, we would like the overall JavaScript community to hash out some approaches for working with the new ES5 property API so we can provide something official and solid in a future version.
On Thu, Oct 18, 2012 at 10:13 AM, Rick Waldron <waldron.rick at gmail.com>wrote:
On Thu, Oct 18, 2012 at 12:59 AM, Dmitry Soshnikov < dmitry.soshnikov at gmail.com> wrote:
On Oct 17, 2012, at 9:34 PM, Axel Rauschmayer wrote:
Pardon, I missed and cannot find what is Object.assign(...), seems it's not from the latest draft. Is it just defining properties (via Object.defineProperty) on from a source to destination object? Like old-good Object.extend(...)?
Explained here: rwldrn/tc39-notes/blob/master/es6/2012-09/sept-18.md
I see, thanks.
So, from what I see:
- Source should not be the one. We should support many of sources to copy all them at once:
Object.assign(dest, source1[, source2, ... sourceN])
I had originally hoped for this, but we reached consensus on Object.assign(dest, source) to allow for a possible descriptor map param.
The pattern you're looking for can be achieved as....
[ defaults, options, overrides ].reduce(Object.assign, {});
In addition:
- If the last parameter is boolean, then it's created as includeNonEnumerable:
Object.assign(desc, source1[, source2, ... sourceN, includeNonEnumerable);
Boolean parameters are a non-starter and would conflict with the desire to have an optional third "default descriptor map" parameter.
In general, it makes sense to be careful about adding new parameters, because it prevents useful extensions in the future.
- If the last parameter is boolean, then it's created as includeNonEnumerable:
Object.assign(desc, source1[, source2, ... sourceN, includeNonEnumerable);
Example;
Object.assign({a: 10}, {b: 20}, Object.defineProperties({}, {c: {value: 30}}), true); // {a: 10, b: 20, c: 30}
That's a slightly dangerous path due to the so-called "Boolean Trap". See e.g. ariya.ofilabs.com/2011/08/hall-of-api-shame-boolean-trap.html.
I’m a bit skeptical about excluding non-enumerable properties for Object.assign(). I still find enumerability a hard concept to wrap my mind around, because it pops up in unexpected places. At the moment, it mostly matters for for...in and Object.keys()/Object.getOwnPropertyNames(). Does it really make sense to increase its role in JavaScript?
Axel