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.seli...@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.giammar...@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 <anguscr...@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.giammar...@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 <anguscr...@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.giammar...@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.giammar...@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.giammar...@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.giammar...@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.giammar...@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@mozilla.org >>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>> >>>>>> >>>>> >>>> >>> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> >
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss