Ciel Ciel - 2 months ago 8
CoffeeScript Question

How to better understand Coffeescript/JavaScript mixins?

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 doing.

  2. Secondly, how does
    extended?.apply(@)
    work? 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

Comments