Object.mixin() reacher proposal

Andrea Giammarchi andrea.giammarchi at gmail.com
Sun Apr 14 22:38:20 PDT 2013


updated API with Trait and the extra argument:
https://github.com/WebReflection/object-mixin#api

how does the code look like now:
https://github.com/WebReflection/object-mixin/blob/master/src/object-mixin.js

is your browser passing all tests? (if green, yes)
http://webreflection.github.io/object-mixin/test/

Best Regards


On Sun, Apr 14, 2013 at 10:23 PM, Andrea Giammarchi <
andrea.giammarchi at gmail.com> wrote:

> not sure changing name is a thing to promote, it makes method name
> clashing easier but it can be achieved simply attaching properties to a
> specific object and then pass that as mixin ...
>
> Object.mixin(target, {
>   on: source.addEventListener,
>   off: source.removeEventListener,
>   has: source.hasEventListener,
>   trigger: source.dispatchEvent
> });
>
> As you see there's no need to make the signature more complex with
> aliases, it's straight forward to do the same, of course if those
> descriptor are meant to be (enumer|configur|writ)able: true)
>
> Agreed on Trait naming convention, but these can be represented only via
> Functions in JS.
>
> However, describing them as "not exactly common function" would result in
> a better understanding.
>
> So here the API, and the name I am afraid has always been abused in JS but
> is known as "mixin"
>
> // basic signature
> Object.mixin(
>   target:Object,
>   source:Object
> ):target
>
> // one overload
> Object.mixin(
>   target:Object,
>   source:Trait
>   [,args:Array|Arguments]
> ):target
>
> This is probably even better than needed/horrible slice call and
> arguments.length check per each mixin invocation with Traits ... so, what
> do you think ?
>
>
>
>
>
>
> On Sun, Apr 14, 2013 at 8:56 PM, Peter Seliger <
> peter.seliger at googlemail.com> wrote:
>
>> Hi, maybe one should discuss terminology first.
>>
>> What has been rediscovered within the last decade every now and again by
>> JavaScript programming individuals, this languages capability for
>> "functional or function based mixins", might deserve a closer look, before
>> running into what I would call a meta programming temptation trap.
>>
>> We already have everything we need in order to create modular collections
>> of behavior and also in order to provide and apply them to objects.
>>
>> "Mixin" might be a Ruby influenced term and does not completely cover
>> what can be achieved by functions/closures [call] and [apply]. I'd rather
>> tend to use Perl 6 "Roles" as a generic term.
>>
>> The smallest thinkable Role was a function body that implements a single
>> method in a stateless way. Thus being a "Trait" if one follows the findings
>> of the "Software Composition Group" at Bern University [
>> http://scg.unibe.ch/research/traits]. Any implementation that gets
>> injected mutable state or does create mutable state on its own in oder to
>> solve its task(s) then, from my point of view, should be referred to as
>> "Mixin".
>>
>> > It seems that Mixins Are Awesome and this can take most advantages from
>> being a function and not only an object:
>> > http://webreflection.blogspot.ie/2013/04/flight-mixins-are-awesome.html
>> >
>> > AFAIK, all interfaces described in W3C such EventTarget and others
>> could be also covered by this proposal ... so ... what do you think ?
>>
>> Andrea, you are right, but all it needs in my opinion are a module
>> pattern, a module library of your choice, a naming convention for your
>> Trait/Mixin-module Implementation (adjectives/adverbes, no nouns, first
>> uppercase letter?) and again [call] or [apply].
>>
>> For your given example of W3C interfaces, [EventTarget] should be
>> implemented and internally referred to as [EventTargetMixin], but the
>> module should expose [EventTargetMixin] as [Observable].
>>
>> - example gist for Observable [https://gist.github.com/petsel/5385218].
>> - example gist for a Trait [https://gist.github.com/petsel/5385163].
>>
>> There is another point that makes pure straightforward functional
>> Trait/Mixin composition unique in JavaScript - passing additional data at
>> apply time. One could write e.g. implementations that at apply time can
>> adapt the naming of their functional API without changing the underlying
>> implementation itself. [Observable] from the above provided  gist example
>> enables configuration of the default API method names by an optionally
>> passed config object making it
>> possible to serve all those weird observable API dialects.
>>
>> var obj_01 = {};
>> var obj_02 = {};
>>
>> Observable.call(obj_01); /* does add the default api methods
>> [addEventListener], [removeEventListener], [hasEventListener] and
>> [dispatchEvent] */
>>
>> Observable.call(obj_02, {
>>   addEventListener: "on",
>>   removeEventListener: "off",
>>   hasEventListener: "hasObserver",
>>   dispatchEvent: "trigger"
>> }); /* obj_02 does feature the custom api names [on], [off],
>> [hasObserver] and [trigger] - the underlying methods are the same as of
>> obj_01 */
>>
>> With meta programming approaches this advantage, one gets for free now,
>> might get lost or if implemented less understandable.
>>
>> I discarded every single approach I made within the last 5 years for
>> Trait/Mixin libraries, that tried to be smarter than what the languages
>> core already provides except the last one that just sticks to a module
>> library.
>>
>>
>>
>>
>> On Sun, Apr 14, 2013 at 11:48 PM, Andrea Giammarchi <
>> andrea.giammarchi at gmail.com> wrote:
>>
>>> somebody already raised the concern "what if I want to mixin the
>>> function as object, not as callable"
>>>
>>> I think being [[Call]] not possible to mixin as object functionality,
>>> and being functions all by default having ownProperties such ["arguments",
>>> "name", "length", "caller"] .. that would simply clash so function as
>>> argument, for this purpose, is never ambiguous, but of course a function
>>> could be the target object, if needed
>>>
>>> var withMoar = Object.mixin(function(){}, mixinFunction);
>>> // same as mixinFunction.call(function(){});
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> On Sun, Apr 14, 2013 at 2:24 PM, Angus Croll <anguscroll at gmail.com>wrote:
>>>
>>>> yeah that's better - I was having a senior moment - most constructor
>>>> functions will normally reside in the prototype of course
>>>>
>>>>
>>>> On Sun, Apr 14, 2013 at 1:59 PM, Andrea Giammarchi <
>>>> andrea.giammarchi at gmail.com> wrote:
>>>>
>>>>> My previous version was doing that in a probably too smart way so I've
>>>>> simplified the proposal simply accepting, in that example
>>>>>
>>>>> Object.mixin(Thung.prototype, Thing.proottype);
>>>>> Object.mixin(Thung.prototype, Thang.proottype);
>>>>>
>>>>> It does not look so black magic anymore but it's way less ambiguous
>>>>> than the first proposal (I guess)
>>>>>
>>>>> Thanks
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Sun, Apr 14, 2013 at 1:34 PM, Angus Croll <anguscroll at gmail.com>wrote:
>>>>>
>>>>>> Lending my support to Object.mixin accepting a function as the
>>>>>> argument—but no surprise there I guess :)
>>>>>>
>>>>>> Note: since functional mixins and constructors are syntactically
>>>>>> identical we can now get gorgeously expressive—and make type inheritance
>>>>>> way simpler (for the first time allowing multiple type inheritance)
>>>>>>
>>>>>> //make a new thing and a new thang
>>>>>> var thing = new Thing;
>>>>>> var thang = new Thang;
>>>>>>
>>>>>> //OR have Thung inherit from Thing and Thang
>>>>>> Object.mixin(Thung.prototype, Thing);
>>>>>> Object.mixin(Thung.prototype, Thang);
>>>>>>
>>>>>>
>>>>>> On Sun, Apr 14, 2013 at 12:59 PM, Andrea Giammarchi <
>>>>>> andrea.giammarchi at gmail.com> wrote:
>>>>>>
>>>>>>> right, I've simplified a lot and tested cross platform:
>>>>>>>
>>>>>>> https://github.com/WebReflection/object-mixin#object-mixin
>>>>>>>
>>>>>>> thoughts?
>>>>>>>
>>>>>>>
>>>>>>> On Sun, Apr 14, 2013 at 10:07 AM, Andrea Giammarchi <
>>>>>>> andrea.giammarchi at gmail.com> wrote:
>>>>>>>
>>>>>>>> OK, maybe just code was a non-sense ...
>>>>>>>>
>>>>>>>> So, the idea behind is mark a function explicitly as mixin ... how ?
>>>>>>>>
>>>>>>>> Any function that is passed and has an empty prototype (then is
>>>>>>>> user defined or native) could be considered invocable as mixin.
>>>>>>>>
>>>>>>>> function addFunctionality() {
>>>>>>>>   this.method = function () {
>>>>>>>>     // now the outer context has a method
>>>>>>>>   };
>>>>>>>> }
>>>>>>>>
>>>>>>>> // mark the prototype as empty in ES5
>>>>>>>> delete addFunctionality.prototype.constructor;
>>>>>>>>
>>>>>>>> function MyClass() {}
>>>>>>>>
>>>>>>>> Object.mixin(MyClass.prototype, addFunctionality);
>>>>>>>>
>>>>>>>> rather than only
>>>>>>>>
>>>>>>>> Object.mixin(MyClass.prototype, {method: function () {}});
>>>>>>>>
>>>>>>>> If the prototype has at least one own property in its prototype it
>>>>>>>> will be considered a constructor so that:
>>>>>>>>
>>>>>>>> Object.mixin(MyClass.prototype, MySuperClass);
>>>>>>>>
>>>>>>>> can easily be transformed implicitly into:
>>>>>>>> Object.mixin(MyClass.prototype, MySuperClass.prototype);
>>>>>>>>
>>>>>>>>
>>>>>>>> This case is, however, less important, the fact Object.mixin should
>>>>>>>> be able to accept a function and invoke it with target as context with
>>>>>>>> optional arguments would be really a **great idea**, IMHO
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On Sun, Apr 14, 2013 at 2:45 AM, Andrea Giammarchi <
>>>>>>>> andrea.giammarchi at gmail.com> wrote:
>>>>>>>>
>>>>>>>>> also, in case you are guessing the typo .. reacher because it
>>>>>>>>> could reach more (older) engines, doing a joke with richer .... got it? ..
>>>>>>>>> too damn fun, I know!
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Sun, Apr 14, 2013 at 2:04 AM, Andrea Giammarchi <
>>>>>>>>> andrea.giammarchi at gmail.com> wrote:
>>>>>>>>>
>>>>>>>>>> apologies
>>>>>>>>>> getOwnPropertyDescriptor(
>>>>>>>>>>     source,
>>>>>>>>>>     key
>>>>>>>>>> )
>>>>>>>>>>
>>>>>>>>>> should have been
>>>>>>>>>> getOwnPropertyDescriptor(
>>>>>>>>>>     enricher,
>>>>>>>>>>     key
>>>>>>>>>> )
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Sun, Apr 14, 2013 at 1:58 AM, Andrea Giammarchi <
>>>>>>>>>> andrea.giammarchi at gmail.com> wrote:
>>>>>>>>>>
>>>>>>>>>>> what I've written here:
>>>>>>>>>>>
>>>>>>>>>>> https://github.com/WebReflection/object-mixin/blob/master/src/object-mixin.js
>>>>>>>>>>>
>>>>>>>>>>> is a better proposal for the potential `Object.mixin()` in
>>>>>>>>>>> current ES6 specs.
>>>>>>>>>>>
>>>>>>>>>>> It seems that Mixins Are Awesome and this can take most
>>>>>>>>>>> advantages from being a function and not only an object:
>>>>>>>>>>>
>>>>>>>>>>> http://webreflection.blogspot.ie/2013/04/flight-mixins-are-awesome.html
>>>>>>>>>>>
>>>>>>>>>>> AFAIK, all interfaces described in W3C such EventTarget and
>>>>>>>>>>> others could be also covered by this proposal ... so ... what do you think ?
>>>>>>>>>>>
>>>>>>>>>>> /*jslint browser: true, forin: true, plusplus: true, indent: 4 */
>>>>>>>>>>> (function(Object, mixin) {
>>>>>>>>>>>     "use strict"; // happy linter ^_____^
>>>>>>>>>>>
>>>>>>>>>>>     /* <droppable>
>>>>>>>>>>>      * adhoc polyfill section for this purpose only
>>>>>>>>>>>      * never use these functions outside this closure ... like
>>>>>>>>>>> ...
>>>>>>>>>>> ne*/var
>>>>>>>>>>>     /*
>>>>>>>>>>> ^ ... you see that? only reason I chose 4 spaces indentations
>>>>>>>>>>> here :D
>>>>>>>>>>>       also this comment ... pure quality, right ?!?! ... anyway
>>>>>>>>>>> ... */
>>>>>>>>>>>
>>>>>>>>>>>         // for IE < 9 Desktop browsers
>>>>>>>>>>>         defineProperty = Object.defineProperty ||
>>>>>>>>>>>         function (o, k, d) {
>>>>>>>>>>>             o[k] = d.value;
>>>>>>>>>>>         },
>>>>>>>>>>>         // same as above
>>>>>>>>>>>         getOwnPropertyNames = Object.getOwnPropertyNames ||
>>>>>>>>>>>         function (o) {
>>>>>>>>>>>             var
>>>>>>>>>>>                 // in case the guy does not inherit from
>>>>>>>>>>> Object.prototype
>>>>>>>>>>>                 has = Object.prototype.hasOwnProperty,
>>>>>>>>>>>                 result = [],
>>>>>>>>>>>                 key;
>>>>>>>>>>>             for (key in o) {
>>>>>>>>>>>                 // in non ES5 compliant browsers
>>>>>>>>>>>                 // there's no way to define properties
>>>>>>>>>>>                 // as non enumerable unless these are
>>>>>>>>>>>                 // there by default, like "constructor" is
>>>>>>>>>>>                 // for functions.prototype
>>>>>>>>>>>                 if (has.call(o, key)) {
>>>>>>>>>>>                     result.push(key);
>>>>>>>>>>>                 }
>>>>>>>>>>>             }
>>>>>>>>>>>             return result;
>>>>>>>>>>>         },
>>>>>>>>>>>         // again ... IE < 8
>>>>>>>>>>>         getOwnPropertyDescriptor =
>>>>>>>>>>> Object.getOwnPropertyDescriptor ||
>>>>>>>>>>>         function (o, k) {
>>>>>>>>>>>             return {
>>>>>>>>>>>                 enumerable: true,
>>>>>>>>>>>                 writable: true,
>>>>>>>>>>>                 configurable: true,
>>>>>>>>>>>                 value: o[k]
>>>>>>>>>>>             };
>>>>>>>>>>>         };
>>>>>>>>>>>     // </droppable>
>>>>>>>>>>>
>>>>>>>>>>>     // if already defined get out of here
>>>>>>>>>>>     // this should be
>>>>>>>>>>>     // if (mixin in Object) return;
>>>>>>>>>>>     // but for some reason I went for JSLint ...
>>>>>>>>>>>     if (Object[mixin]) {
>>>>>>>>>>>         return;
>>>>>>>>>>>     }
>>>>>>>>>>>     // same descriptor as other spec'd methods
>>>>>>>>>>>     defineProperty(
>>>>>>>>>>>         Object,
>>>>>>>>>>>         mixin,
>>>>>>>>>>>         {
>>>>>>>>>>>             enumerable: false,
>>>>>>>>>>>             writable: true,
>>>>>>>>>>>             configurable: true,
>>>>>>>>>>>             value: function mixin(
>>>>>>>>>>>                 target, // object to enrich with
>>>>>>>>>>>                 source    // mixin object/function
>>>>>>>>>>>             ) {
>>>>>>>>>>>                 var
>>>>>>>>>>>                     // check if source is a function
>>>>>>>>>>>                     enricher = typeof source === 'function' ?
>>>>>>>>>>> source.prototype : source,
>>>>>>>>>>>                     // per each own property name
>>>>>>>>>>>                     keys = getOwnPropertyNames(enricher),
>>>>>>>>>>>                     length = keys.length,
>>>>>>>>>>>                     i = 0,
>>>>>>>>>>>                     key;
>>>>>>>>>>>                 while (i < length) {
>>>>>>>>>>>                     // define it ...
>>>>>>>>>>>                     defineProperty(
>>>>>>>>>>>                         target,
>>>>>>>>>>>                         key = keys[i++],
>>>>>>>>>>>                         // ... via same property descriptor
>>>>>>>>>>>                         getOwnPropertyDescriptor(
>>>>>>>>>>>                             source,
>>>>>>>>>>>                             key
>>>>>>>>>>>                         )
>>>>>>>>>>>                     );
>>>>>>>>>>>                 }
>>>>>>>>>>>                 // if the object had no own names
>>>>>>>>>>>                 // it's quite clear the intention of the user
>>>>>>>>>>>                 // so that if a function without properties
>>>>>>>>>>>                 // is passed through this method ...
>>>>>>>>>>>                 if (!length && typeof source === 'function') {
>>>>>>>>>>>                     // this function is invoked with the target
>>>>>>>>>>>                     // as its own context
>>>>>>>>>>>                     source.apply(
>>>>>>>>>>>                         target,
>>>>>>>>>>>                         // optional arguments to initialize
>>>>>>>>>>> defaults
>>>>>>>>>>>                         // for this mixin might be accepted too
>>>>>>>>>>>                         keys.slice.call(arguments, 2)
>>>>>>>>>>>                     );
>>>>>>>>>>>                 }
>>>>>>>>>>>                 // always return the initial target
>>>>>>>>>>>                 // ignoring a possible different return
>>>>>>>>>>>                 // in latter case: consistency with this method
>>>>>>>>>>>                 return target;
>>>>>>>>>>>             }
>>>>>>>>>>>         }
>>>>>>>>>>>     );
>>>>>>>>>>> }(Object, 'mixin'));
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> es-discuss mailing list
>>>>>>> es-discuss at mozilla.org
>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130414/03ceff30/attachment-0001.html>


More information about the es-discuss mailing list