Object.mixin() reacher proposal
apologies getOwnPropertyDescriptor( source, key )
should have been getOwnPropertyDescriptor( enricher, key )
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')); > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130414/f476d329/attachment-0001.html>
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!
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')); >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130414/5c945f11/attachment.html>
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
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')); >>> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130414/203aeae4/attachment-0001.html>
right, I've simplified a lot and tested cross platform:
WebReflection/object-mixin#object-mixin
thoughts?
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')); >>>> >>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130414/2a878fd1/attachment.html>
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);
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 > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130414/4e8df5af/attachment-0001.html>
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)
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 >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130414/c10217c6/attachment-0001.html>
yeah that's better - I was having a senior moment - most constructor functions will normally reside in the prototype of course
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 >>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130414/6cd45c95/attachment-0001.html>
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(){});
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 >>>> >>>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20130414/37dddc18/attachment-0001.html>
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 [ 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: 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 [gist.github.com/petsel/5385218].
- example gist for a Trait [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.
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/20130415/adcf4c1b/attachment-0001.html>
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 ?
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/05159a24/attachment-0001.html>
updated API with Trait and the extra argument: WebReflection/object-mixin#api
how does the code look like now: WebReflection/object-mixin/blob/master/src/object-mixin.js
is your browser passing all tests? (if green, yes) webreflection.github.io/object-mixin/test
Best
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>
what I've written here: 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: 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 ^_____^
ne*/var /* ^ ... you see that? only reason I chose 4 spaces indentations here :D also this comment ... pure quality, right ?!?! ... anyway ... */
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'));