Ciel Ciel - 2 months ago 9
Javascript Question

Coffeescript/Javascript Mixins - Idiot Seeking Explanation

I have been reading up on

Mixins
using
Coffeescript
or just plain
Javascript
from the following sources ...

http://arcturo.github.com/library/coffeescript/03_classes.html (near the bottom)

and

http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/

And while I am able to compile the various examples, I have a major question that seems to be preventing me from making progress in comprehending them.

I have no idea what in the world is going on ...



To start, I will explain the coffeescript that is confusing me...

moduleKeywords = ['extended', 'included']

class Module
@extend: (obj) ->
for key, value of obj when key not in moduleKeywords
@[key] = value

obj.extended?.apply(@)
this

@include: (obj) ->
for key, value of obj when key not in moduleKeywords
# Assign properties to the prototype
@::[key] = value

obj.included?.apply(@)
this


A number of questions come up here.

1. First of all, what are we accomplishing with the
moduleKeywords
variable? I'm not understanding what that is even doing.



2. Secondly, what is up with the
extended?.apply(@)
? What is really going on here? I can look at the javascript compilation and see the following code ..



Module.extend = function(obj) {
var key, value, _ref;
for (key in obj) {
value = obj[key];
if (__indexOf.call(moduleKeywords, key) < 0) {
this[key] = value;
}
}
if ((_ref = obj.extended) != null) {
_ref.apply(this);
}
return this;
};


Can anyone shed some general light on this?

From deeper down in
The Little Book on Coffeescript
, I see an implementation.



ORM =
find: (id) ->
create: (attrs) ->
extended: ->
@include
save: ->

class User extends Module
@extend ORM


Here is how I read this ...


  • create literal
    ORM
    .

  • Declare method
    find
    accepting a parameter.

  • Declare method 'create' accepting a parameter.

  • Declare method 'extended', with sub-method 'include', with sub-method 'save'.



This is where I get the most lost.



The literal
ORM
has a method,
extended
, and then
Module
is implemented/extended by the 'class'
User
. So I take this to mean that
User
has the same shape as
Module
. That part makes sense so far, simplistic inheritance. But then I get lost on
@extend ORM
.

@extend
is a method on
Module
, but what is the
extended
method doing? When is it called? How is it implemented?

Answer
  • extend copies the methods from the "module" object onto the object being extended
  • include copies the methods from the "module" object onto the prototype of the object being extended

1 The moduleKeywords is used to protect some methods of the module, so the are not copied to object, because they have special meaning

2 The extended?.apply(@) says that if the module has a property named extended than assume it's a function and then call this function having the "this" in the function equal to @, @ being the extended object, you can think of it as saying something like (although not quite, but it's just an intuition) @.extended() (@ == this in coffeescript)

"apply" function in JS
the existential operator in CS