> `Object.assign` has **nothing to do with inheritance**, that's what I am 
> saying, not just supporting.
> What is my personal position here is that `Object.assign` is the wrong 
> method/tool/function to do anything prototypal or classical inheritance 
> related.


Are we entirely missing each other? I’ve said a few times now: it’s _none_ of 
the callee’s business if I use inheritance in my options, config, setup or any 
other plain object (one without behavior). Object.assign must honor that.

I asked in my first email: What is the problem to which ignoring inherited 
properties is the solution to?
If you have an argument that I haven’t refuted yet, please share.

Just search GitHub’s code for assign usage and you’ll see it fucking up 
inheritance all over the place.
There’s even a IO.js issue for the same problem that I’m definitely going to 
help fix: https://github.com/iojs/io.js/issues/62.

Andri Möll:
> Nah, I’m saying inheritance is an implementation detail of my object. It’s 
> none of the receiver’s/callee’s business how I implemented that particular 
> interface (any agreed upon set of properties _is_ an interface). But the 
> moment someone passes my object to Object.assign, they get the wrong output. 
> Even if it should’ve been a no-op: `options = Object.assign({}, options)`.
> 
> Ignores getters? You mean merely reads them? That’s not ignoring. Getters are 
> an implementation detail of an interface.
> Prototypes aren't only useful for sharing behavior. They’re just as useful 
> for data objects and value types. Nothing breaks when you clone or assign 
> them around.
> 
> 
> Inheritance? Inheritance is an implementation detail. A function receiving an 
> object must not care about its inheritance tree as long as it fulfills the 
> required interface. That’s what the LSP says as well. Even though JavaScript 
> has no explicit concept of interfaces or types, they’re implicit in any 
> function call.

A.

On Feb 27, 2015, at 23:13, Andrea Giammarchi <[email protected]> 
wrote:

> FWIW I do like prototypal inheritance ... but ... 
> 
> On Fri, Feb 27, 2015 at 8:45 PM, Andri Möll <[email protected]> wrote:
>> That is not what people relying in Object.assign and ES6 will write, because 
>> you cannot define properties in a generic class, only methods.
> 
> Classes are just syntactic sugar over prototypes after all.
> 
> except finally these behave like natives always have: non enumerable methods 
> / accessors ... those that even you said don't want on your way
> 
>  
> I’m definitely going to continue promoting use of plain old prototypical 
> approaches in addition to that because they're simple and elegant:
> 
> objects will still be used for composing and whenever you 
> `Object.create(Object.getPrototypeOf(other))` you are still using prototypal 
> inheritance.
> 
> None of this has ever been solved in `Object.assign` though ... 
> 
>  
> why waste computation power in constructors when you can do so once on the 
> prototype.
> 
> 'cause 99% of the time you need to initialize your PERSON with a `name` 
> property, as example ... do that in the object creation through an implicit 
> initializer as constructor is: done!
> 
>  
> I find that an advantage of prototypal languages over classical ones.
> 
> I guess you like `init` methods too then
> 
> 
>  
> 
> A bit of a plug in this regard, check out this simple observable 
> implementation that supports inheritance: https://github.com/moll/js-concert
> Boy does this save computation. No need to bind listeners for every object 
> (e.g. domain model) instance:
> Model.prototype.on(“change”, onChange) is all you need. Beautiful, isn’t it? 
> ;-)
> 
> Check what DOM offered since about ever: EventListener interface:
> http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener
> 
> You inherit this:
> 
> ```js
> 
> class EventListener {
>   handleEvent(e) {
>     var type = 'on' + e.type;
>     if (type in this) this[type](e);
>   }
> }
> 
> ```
> 
> And BOOM, every class inheriting that will be able to create instances usable 
> as handlers, no need bind listeners to anything anymore!
> 
> ```js
> 
> class DaClicker extends EventListener {
>   constructor(el) {
>     el.addEventListener('click', this);
>   }
>   onclick(e) {
>     alert([e.type, this instanceof DaClicker]);
>   }
> }
> 
> var driver = new DaClicker(document);
> 
> ```
> 
> How cool is that? Now, let's go back to `Object.assign` ...
> 
>  
> 
> Well, that didn’t seem to prevent changing class method enumerability just a 
> little time ago.
> 
> and didn't affect `Object.assign` behavior ... we all agreed here 
> enumerability had to be changed in order to be consistent with native classes 
> and be able to extend them without causing unexpected behaviors ... it was 
> the last window before breaking classes forever, while `Object.assign` is a 
> method based on old ES3 concepts that has not much to do with ES6 and that 
> was never meant to be used to extend objects. It's the wrong tool for the 
> job, accessors are lost in the process, and everything else is ignored, 
> including inheritance.
> 
> 
> 
> Sweet story you made out of the example. :-) Coming back to non-prose for a 
> sec, unless you get everyone to ignore Object.assign and use your function, 
> there’s no point in proposing your functions. That’s what I’ve now repeated 
> plenty of times. It’s going to hurt _us_ prototype-uses because _others_ will 
> use Object.assign where they need not.
> 
> There's no point in proposing `Object.assign` to deal with inheritance, 
> prototypal inheritance, and de-facto extend ability. `Object.assing` has one 
> well defined use case: copy own enumerable properties, that's it ... 
> **really** ... that's just it. Good for setup or config options, nothing else!
> 
> 
> 
>  
> Umm, that was already explained by Leon Arnott’s email: Object.assign is 
> cowpath pavement. Everyone seems to like a for-in assignment helper. Two of 
> most popular assign/extend implementation mentioned (jQuery, Underscore) have 
> supported inheritance for _at least_ 7 years. Do you not find that as 
> evidence “from the field"?
> 
> common extend do not loop over inherited properties, if these do is because 
> these were written in an era where `Object.getPrototypeOf` and 
> `Object.setPrototypeOf` where missing.
> 
> You talked about computation power and you want to loop over everything per 
> each `Object.assign` call ... I am sorry I don't follow you anymore here!
> 
>  
> 
> Or am I preaching to the choir? Are you personally already in favor of 
> supporting inheritance in Object.assign?
> 
> `Object.assign` has **nothing to do with inheritance**, that's what I am 
> saying, not just supporting.
> 
> 
>  
> Given what I’ve read from you so far you won’t be affected by it as it seems 
> to me you prefer to use this prototypal language in a classical way.
> 
> 
> No, I do like prototypal inheritance and I love the fact it's still the root 
> of JS inheritance.
> 
> What is my personal position here is that `Object.assign` is the wrong 
> method/tool/function to do anything prototypal or classical inheritance 
> related.
> 
> Developers should understand it, and I am realizing they don't ... like not 
> at all!
> 
> Best Regards
> 
>  
> 
> A.
> 
> On Feb 27, 2015, at 19:51, Andrea Giammarchi <[email protected]> 
> wrote:
> 
>> That is not what people relying in Object.assign and ES6 will write, because 
>> you cannot define properties in a generic class, only methods.
>> 
>> Moreover, back to your ES5/3compat example, if you have a person object, you 
>> **never** inherit name, you always have your own name as you explicitly set 
>> "John".
>> 
>> You eventually inherit the surname, but that's indeed not your own so it 
>> should not be copied as such, it should stay there inherited unless you 
>> explicitly go to the inheritance office (the property descriptor officer) 
>> and ask for an own surname.
>> 
>> Same is for all people from Estonia, they all inherit their native country 
>> when born, they have to hide it explicitly at the same "descriptor office" 
>> in order to make them their own country.
>> 
>> But all this goes down to why/how/where you need to retrieve these info. 
>> That is the place you log through a for/in in order to reach all exposed 
>> (read enumerables) properties.
>> That is where you log passing whatever it is through the function I've 
>> written.
>> 
>> Before? country isan accessible info, as the surname and other inherited 
>> properties eventually would be, and only if re-set on top, will become own 
>> properties.
>> 
>> At the end of the day, `Object.assign` has been already adopted and 
>> polyfilled and used for some time now, changing it now will probably break 
>> all code based on it.
>> 
>> Again, I think this is the first time I hear someone wanting a new method 
>> being exactly like a for/in ... use for/in if that's what you need ( KISS ? )
>> 
>> Best Regards
>> 
>> 
>> On Fri, Feb 27, 2015 at 5:27 PM, Andri Möll <[email protected]> wrote:
>>> ES3 these are all enumerable, you don't want methods copied all over your 
>>> objects each time because that's the entire point of having prototypal 
>>> inheritance, right? If instead of inheriting and composing you copy 
>>> everything as enumerable, writable, and configurable, that's your choice, 
>>> not what I believe we all need.
>> 
>> Umm, that’s one tactic for sharing behavior. Yep. But I thought we agreed 
>> Object.assign is more useful for data/record objects than for objects with 
>> behavior. Ignoring inheritance because of methods is not an argument then.
>> 
>>> You yourself said one shouldn’t use Object.assign for objects with behavior 
>>> in the inheritance chain. And I agree. It’s pretty much only useful for 
>>> data objects (a.k.a plain). Those have no methods in the inheritance chain 
>>> one needs to ignore.
>>> 
>>> meaning you are good to go with assign or the function I wrote for you.
>> 
>> 
>> Sadly not. Inheritance should not be conflicted with sharing behavior 
>> (methods). Entirely orthogonal concepts. It’s very useful to inherit from 
>> various data/record objects and pass those around. The receiver of such an 
>> object need never know there’s inheritance involved.
>> 
>>> [ 1 ] What is the problem in accessing inherited values?
>>> If you don't want to distinguish them, just don't and use a for/in
>>> Why do you want now to change Object assign instead of simply using for/in? 
>>> This requirement is available since 1999
>> 
>> They thing to remember here is _other people’s code_. My code perfectly 
>> honors your inheritance chains when iterating or accessing properties. But 
>> me doing that doesn’t imply everyone else won’t use Object.assign to set up 
>> their defaults as is very convenient: `person = Object.assign({name: “”, 
>> age: 0}, person)`. You think they won’t? They already do so with Object.keys 
>> when it’s entirely unnecessary for 9/10 use-cases.
>> 
>>> You seem to be afraid of inheritance since you want to ignore it and flat 
>>> all the properties per each copied/enriched object.
>>> I am back with previous [ 1 ] question then.
>> 
>> 
>> Nah, I’m saying inheritance is an implementation detail of my object. It’s 
>> none of the receiver’s/callee’s business how I implemented that particular 
>> interface (any agreed upon set of properties _is_ an interface). But the 
>> moment someone passes my object to Object.assign, they get the wrong output. 
>> Even if it should’ve been a no-op: `options = Object.assign({}, options)`.
>> 
>>> You can define you r`toJSON` method that returns the result of the for/in 
>>> based function I've written for you. Is that retarded?
>> 
>> 
>> I’ll leave JSON out of this discussion. Yeah, I’d like to set 
>> Object.prototype.toJSON, but I’m afraid there’s code somewhere that depends 
>> on it serializing only own properties. Ugh.
>> 
>>> Precisely !  So use inheritance instead of flattening/hiding it everywhere. 
>>> Use dictionaries and for/in when all this does not matter.
>> 
>>> I really don't see, with all possibilities you have to write the way you 
>>> want, and a function I wrote for you that does what you need, why bothering 
>>> `Object.assign` 
>> 
>> 
>> But it’s not me who wants to flatten stuff. It’s the people who will write 
>> functions or APIs that use Object.assign while setting their defaults. I 
>> don’t mind them flattening, but only if they don’t lose half of the 
>> properties to inheritance stripping while doing so.
>> 
>> Am I explaining the problem wrong? I’m still surprised there are people who 
>> don’t find the following behavior retarded:
>> 
>> ```
>> function logPerson(person) { console.log(“%s is from %s.”, person.name, 
>> person.country) } 
>> function logTraveler(person) { logPerson(Object.assign({name: “Traveller”}, 
>> person)) } 
>> 
>> var PERSON = {name: “Unnamed”, country: “Estonia"}
>> var john = Object.create(PERSON)
>> john.name = “John”
>> 
>> logPerson(john) // => John is from Estonia.
>> logTraveler(john) // => John is from undefined.
>> ```
>> 
>> While a little contrived, like I said, Object.assign and its equivalents 
>> from libraries are already used to set defaults.
>> Just in case: please don’t propose replacing every Object.create with 
>> Object.assign.
>> 
>> A.
>> 
>> On Feb 27, 2015, at 18:35, Andrea Giammarchi <[email protected]> 
>> wrote:
>> 
>>> answering inline ...
>>> 
>>> On Fri, Feb 27, 2015 at 2:22 PM, Andri Möll <[email protected]> wrote:
>>>> noone? JSLint doesn't even let you write a for/in loop if you don't have 
>>>> `obj.hasOwnProperty(key)` in it, and usually nobody wants inherited 
>>>> properties (included methods from old classes/ahem prototypes) reassigned 
>>>> everywhere.
>>> 
>>> Huh? Old prototypes? Those prototypes have their properties set as 
>>> non-enumerable since how long now?
>>> 
>>> nope, I was rather talking about user-land defined "classes" through 
>>> prototypes. in ES3 these are all enumerable, you don't want methods copied 
>>> all over your objects each time because that's the entire point of having 
>>> prototypal inheritance, right? If instead of inheriting and composing you 
>>> copy everything as enumerable, writable, and configurable, that's your 
>>> choice, not what I believe we all need.
>>> 
>>> 
>>>  
>>> You yourself said one shouldn’t use Object.assign for objects with behavior 
>>> in the inheritance chain. And I agree. It’s pretty much only useful for 
>>> data objects (a.k.a plain). Those have no methods in the inheritance chain 
>>> one needs to ignore.
>>> 
>>> meaning you are good to go with assign or the function I wrote for you.
>>> 
>>> 
>>>  
>>> 
>>> Again, I ask, what is the problem to which ignoring inherited properties is 
>>> the solution to?
>>> 
>>> 
>>> 
>>> [ 1 ] What is the problem in accessing inherited values?
>>> 
>>> If you don't want to distinguish them, just don't and use a for/in
>>> 
>>> Why do you want now to change Object assign instead of simply using for/in? 
>>> This requirement is available since 1999
>>> 
>>> 
>>>  
>>> I posit everyone wants inherited properties. Just half of the people have 
>>> been FUDed into being afraid of inheritance. But arguments based on 
>>> assumptions on what other people want are irrelevant because naive people 
>>> are easy to influence. 
>>> 
>>> You seem to be afraid of inheritance since you want to ignore it and flat 
>>> all the properties per each copied/enriched object.
>>> I am back with previous [ 1 ] question then.
>>> 
>>> 
>>>  
>>> JSLint is how Douglas Crockford writes his code. That’s not an argument for 
>>> right APIs. JSON.stringify is equally retarded with its inconsistent 
>>> handling of inheritance, but that’s another matter.
>>> 
>>> You can define you r`toJSON` method that returns the result of the for/in 
>>> based function I've written for you. Is that retarded?
>>> 
>>> Moreover, you can recreate instances at parse time with a specialized 
>>> reviver: https://gist.github.com/WebReflection/87e41c09691edf9432da
>>> Is that retarded? ( maybe this one is :P )
>>> 
>>>  
>>> 
>>> And as I said below: until everyone also prefixes their obj.name uses with 
>>> hasOwn: `obj.hasOwnProperty(“name”) && obj.name`, skipping inherited 
>>> properties is a fool’s errand. It causes inconsistent APIs because you 
>>> don’t run your options et alii objects through inheritance strippers every 
>>> time. And you shouldn’t. Or does anyone disagree with that?
>>> 
>>> actually, following your logic you should never access that unless you are 
>>> sure it's also enumerable so ... 
>>> 
>>> `obj.hasOwnProperty("name") && obj.propertyIsEnumerable("name") && 
>>> obj.name``
>>> 
>>>  
>>> 
>>> This is a bigger problem than my use of Object.assign. Proliferation of 
>>> Object.assign will prevent everyone else from relying on inheritance. And 
>>> in a prototypal language I find that bad API design.
>>> 
>>> Precisely !  So use inheritance instead of flattening/hiding it everywhere. 
>>> Use dictionaries and for/in when all this does not matter.
>>> 
>>> I really don't see, with all possibilities you have to write the way you 
>>> want, and a function I wrote for you that does what you need, why bothering 
>>> `Object.assign` 
>>> 
>>> Best Regards
>>> 
>>> 
>>>  
>>> 
>>> A.
>>> 
>>> On Feb 27, 2015, at 15:40, Andrea Giammarchi <[email protected]> 
>>> wrote:
>>> 
>>>> noone? JSLint doesn't even let you write a for/in loop if you don't have 
>>>> `obj.hasOwnProperty(key)` in it, and usually nobody wants inherited 
>>>> properties (included methods from old classes/ahem prototypes) reassigned 
>>>> everywhere.
>>>> 
>>>> If you deal with data objects and dictionaries yuo'll always have a flat 
>>>> structure, right? If you don't care about properties descriptors (getters 
>>>> and setters) you can always use a for/in
>>>> 
>>>> ```
>>>> function flatEnumerables(a) {
>>>>   for (var c, k, i = 1; i < arguments.length; i++) {
>>>>     for (k in (c = arguments[i])) a[k] = c[k];
>>>>   }
>>>>   return a;
>>>> }
>>>> ```
>>>> This would do what you are looking for (which is the first time I 
>>>> personally read/hear about somebody wanting `Object.assign` to behave like 
>>>> a for/in)
>>>> 
>>>> Would that work?
>>>> 
>>>> Best Regards
>>>> 
>>>> 
>>>> 
>>>> On Fri, Feb 27, 2015 at 12:56 PM, Andri Möll <[email protected]> wrote:
>>>>> You are talking about "flatting" all properties, which is an undesired 
>>>>> overhead.
>>>> 
>>>> Umm, Object.assign is as it is because of performance? I don’t think it is 
>>>> nor is that a good reason. Every property access in JavaScript takes 
>>>> inheritance into account and there are thousands more than a Object.assign 
>>>> call here and there.
>>>> 
>>>>> But what's bugging me every time more, is that somebody had a very bad 
>>>>> idea to spread `Object.assign` as something good for inheritance or 
>>>>> object cloning.
>>>>> 
>>>>> Where does this come from? `Object.assign` retrieves properties and 
>>>>> ignore getters and setters, is the last tool you want to use as 
>>>>> substitution principle because it breaks.
>>>> 
>>>> 
>>>> Ignores getters? You mean merely reads them? That’s not ignoring. Getters 
>>>> are an implementation detail of an interface.
>>>> Prototypes aren't only useful for sharing behavior. They’re just as useful 
>>>> for data objects and value types. Nothing breaks when you clone or assign 
>>>> them around.
>>>> 
>>>> Object.assign just read properties from one object and assign them to 
>>>> another. Something you used to do by hand. It’s just shorter to type 
>>>> assign(A, B) than type all properties of B out manually. If it’s _not_ 
>>>> meant to be the function-equivalent of `for (var key in source) 
>>>> target[key] = source[key]` then that’s too bad as my money is on it’s 
>>>> going to be used as such. I definitely want to use it for that.
>>>> 
>>>>> But what's bugging me every time more, is that somebody had a very bad 
>>>>> idea to spread `Object.assign` as something good for inheritance or 
>>>>> object cloning.
>>>> 
>>>>> Are you dealing with prototypes and `Object.assign` ? You gonna have way 
>>>>> more problems than a missed flattered structure.
>>>>> Can you explain what is your goal ? Wouldn't this work?
>>>> 
>>>> Inheritance? Inheritance is an implementation detail. A function receiving 
>>>> an object must not care about its inheritance tree as long as it fulfills 
>>>> the required interface. That’s what the LSP says as well. Even though 
>>>> JavaScript has no explicit concept of interfaces or types, they’re 
>>>> implicit in any function call.
>>>> 
>>>> My goal is to save people from having to think every time they call a 
>>>> function whether this 3rd party function ignores inherited properties or 
>>>> not. If the callee uses Object.assign, it strips them out, if not, the 
>>>> dot-operator takes it into account. Surely no-one’s expecting everyone to 
>>>> prefix _every_ obj.name use with hasOwn: `obj.hasOwnProperty(“name”) && 
>>>> obj.name`. Why do it in Object.assigns then is beyond me. Inconsistent and 
>>>> uncalled for.
>>>> 
>>>> A.
>>>> 
>>>> On Feb 27, 2015, at 14:24, Andrea Giammarchi <[email protected]> 
>>>> wrote:
>>>> 
>>>>> You are talking about "flatting" all properties, which is an undesired 
>>>>> overhead.
>>>>> 
>>>>> ```js
>>>>> 
>>>>> var b = Object.create(
>>>>>   Object.getPrototypeOf(a)
>>>>> );
>>>>> 
>>>>> Object.assign(b, a);
>>>>> 
>>>>> ```
>>>>> 
>>>>> But what's bugging me every time more, is that somebody had a very bad 
>>>>> idea to spread `Object.assign` as something good for inheritance or 
>>>>> object cloning.
>>>>> 
>>>>> Where does this come from? `Object.assign` retrieves properties and 
>>>>> ignore getters and setters, is the last tool you want to use as 
>>>>> substitution principle because it breaks.
>>>>> 
>>>>> `Object.assign` is good only to define enumerable, writable, and 
>>>>> configurable properties, like configuration or setup objects.
>>>>> 
>>>>> Are you dealing with prototypes and `Object.assign` ? You gonna have way 
>>>>> more problems than a missed flattered structure.
>>>>> 
>>>>> Can you explain what is your goal ? Wouldn't this work?
>>>>> 
>>>>> ```js
>>>>> 
>>>>> var a = {}; // or anything else
>>>>> 
>>>>> var b = Object.create(
>>>>>   Object.getPrototypeOf(a)
>>>>> );
>>>>> 
>>>>> Object.getOwnPropertyNames(a).forEach(function (k) {
>>>>>   Object.defineProperty(b, k, Object.getOwnPropertyDescriptor(a, k));
>>>>> });
>>>>> 
>>>>> ```
>>>>> 
>>>>> 
>>>>> Best Regards
>>>>> 
>>>>> 
>>>>> 
>>>>> On Fri, Feb 27, 2015 at 11:52 AM, Andri Möll <[email protected]> wrote:
>>>>> Hello,
>>>>> 
>>>>> Why does Object.assign ignore inherited enumerable properties?
>>>>> What is the problem to which ignoring inherited properties is the 
>>>>> solution to?
>>>>> 
>>>>> All I can see is that it prevents a useful use of inheritance. The Liskov 
>>>>> substitution principle was mentioned 27 years ago in ’87. Why is 
>>>>> Object.assign breaking it?
>>>>> 
>>>>> - Everyone who’s messing with Object.prototype has to do it an 
>>>>> non-enumerable style anyway.
>>>>> - Most uses of Object.assign will likely be for objects with a finite 
>>>>> number of keys. Those form specific and implicit types from which people 
>>>>> are likely to read with the dot-operator. That takes inheritance into 
>>>>> account anyway.
>>>>> 
>>>>> I don’t get the agenda to mess with object inheritance. If one wants 
>>>>> methods to only be in the parent and data on the child (so Object.assign 
>>>>> would only copy data), use a classical language. In a 
>>>>> delegation-prototypal language one should be able to inherit freely 
>>>>> because of LSP.
>>>>> 
>>>>> Andri
>>>>> 
>>>>> _______________________________________________
>>>>> es-discuss mailing list
>>>>> [email protected]
>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>> 
>>>>> 
>>>> 
>>>> 
>>> 
>>> 
>> 
>> 
> 
> 

Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to