This is all pretty self-explanatory. We’re using node.js to require the
Now that we have our objects, let’s reopen our class/prototype and add some new behavior. This was one of the first things I found interesting (and later dangerous (and later interesting again)) about ruby. Turns out this is a piece of cake in JS as well.
In ruby we reopen the class simply using the
Next up we’ll add some behavior to specific instances. We want to add a method for throwing stars only to the
drew instance, not the
adam instance. Here’s the code.
In ruby, we add a method to the
drew object using
The next thing we’ll look at is calling methods dynamically. The ability to call a method with a name given to us at runtime is a powerful tool in DSL creation and metaprogramming. Here’s the code.
This is very trivial in both languages. Ruby allows us to call methods based on strings or symbols using the
send method, whereas JS allows us to use the square bracket syntax to access members of objects with strings. We then tack on the parentheses to call the method which we’ve retrieved from the object.
Now, let’s get into a meatier topic: defining methods dynamically with closures. What we want is the ability to define a method dynamically (given a name) that is also a closure over the lexical scope at the point of method definition. This means we will have access to variables, methods, and classes that are available at the time of the method defintion. Read the code below and then I’ll describe what’s happening here.
Let’s look at the ruby code first. You may notice that we’re using
send to call
define_method. This is a trick (hack) in ruby that allows us to call private methods without
self being the implicit receiver.
define_method takes a name for the new method and a block which describes the body of the method. In ruby, this block is a closure which means we have access to the scope at the time of the method definition. In the code example above, we take advantage of having access to the scope by returning the color defined outside of the method. This would be impossible if our block was not a closure because there is no guarantee that we would have access to this variable at the time of the method call.
Let’s end with one final example: defining a method dynamically on an instance that closes over local scope and accesses the instance’s state. Code first, description second.
We’ll talk about the ruby example first because it needs more explanation. You can see the first thing we do is reopen the
Object class to define a method called
metaclass. This method retrieves an object’s metaclass (or ghostclass (or eigenclass (or whatever))). You can think of a metaclass as a class definition specific to a single instance of a class. This means we can add methods to an object’s metaclass without adding the same behavior to all instances of that object’s class. So we grab our ninja’s metaclass and then define a method using
define_method, identical to the previous example of define a method on the class. One interesting thing to note is that we are calling the
name method in the body of our
define_method block. This is to show that our method has access to the instance’s state.