Created
June 17, 2013 21:57
-
-
Save codebycliff/5800853 to your computer and use it in GitHub Desktop.
The JavaScript generated for a simple CoffeeScript class with explanations / annotations.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* CoffeeScript: | |
class Person | |
constructor: (@name, @age) -> | |
@createdAt = new Date() | |
isAdult: => @age > 18 | |
talk: => console.debug("Hello. My name is #{@name} and I'm #{@age} years old.") | |
*/ | |
// Anonymously invoked function serving as namespace that creates a new scope | |
(function() { | |
// Global variable that will store the Person constructor function | |
var Person, | |
// Global function that binds the specified function (fn) to the specified scope (me). | |
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; | |
// Anonymously invoked function serving as a class definition using a closure | |
Person = (function() { | |
function Person(name, age) { | |
// Set properties | |
this.name = name; | |
this.age = age; | |
// Bind prototype functions to the scope (in this case, the Person function). | |
// | |
// This means that inside the prototype function, the keyword 'this' | |
// (a.k.a. the scope) refers to value of 'this' inside this Person | |
// function, which allows the prototype function to have access to | |
// whatever is defined on 'this' inside this Person function. | |
// | |
// Without the lines below (just the prototype definitions), the | |
// scope (the value of the keyword 'this') could refer to anything. | |
// For example, looping using jQuery's each function: | |
// | |
// var bob = new Person('Bob', 44); | |
// $('a').each(bob.talk); | |
// | |
// The value of the keyword 'this' (a.k.a. the scope) during the | |
// execution of the talk method would refer to the jQuery object | |
// for the anchor. This means it would blow up without binding | |
// because jQuery doesn't have the 'name' and 'age' properties. | |
this.talk = __bind(this.talk, this); | |
this.isAdult = __bind(this.isAdult, this); | |
} | |
// Define prototypes | |
Person.prototype.isAdult = function() { | |
// The value of this is guaranteed to point to the constructor | |
// function because of the binding done on the previous lines. | |
return this.age > 18; | |
}; | |
Person.prototype.talk = function() { | |
return console.debug("Hello. My name is " + this.name + " and I'm " + this.age + " years old."); | |
}; | |
// Return the Person constructor function. This is an example of | |
// how a closure works: | |
// | |
// Everything defined inside the anonymously invoked function | |
// is private / not accessible from the global scope. The Person variable | |
// above is simply being set to whatever this current anonymously invoked | |
// function returns. Therefore, if you omitted this line, Person would have | |
// the value of null. This would be the same as if everything defined inside | |
// this anonymously invoked function never existed. Instead, we create a | |
// FUNCTION that initializes some properties. We then add some methods | |
// to that FUNCTION's prototype. We then return that FUNCTION, which | |
// has the prototypes defined on it, which serves as a constructor | |
// function. | |
return Person; | |
})(); | |
// Call the outer namespace function using the global scope (usually window, or | |
// exports in node). This means that the only things available to the global scope | |
// are the Person and __bind functions. | |
}).call(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment