Classes: Giving Prototypes Structure

To reap the benefits of prototypal inheritance in JavaScript, you have to define a constructor and then attach properties to its associated prototype. CoffeeScript allows you to do both of those things at once using the class keyword:

 class​ MyFirstClass
  sayHello: -> console.log ​"Hello, I'm a class!"
 
 myFirstInstance = ​new​ MyFirstClass
 myFirstInstance.sayHello()
 Hello, I'm a class!

In just two lines, we’ve defined a no-op constructor named MyFirstClass and attached a method called sayHello to its prototype. Of course, we could do that in two lines without the class keyword. So let’s look at a more involved example.

It’s a well-known fact that the trouble a tribble makes is directly proportional to the number of existing tribbles. Let’s write a class that demonstrates that wisdom:

 class​ Tribble
  constructor: ->
  @isAlive = true
  Tribble.count += 1
 
 # Prototype properties
  breed: -> ​new​ Tribble ​if​ @isAlive
  die: ->
 return​ unless @isAlive
  Tribble.count -= 1
  @isAlive = false
 
 # Class-level properties
  @count: 0
  @makeTrouble: -> console.log (​'Trouble!'​ ​for​ i ​in​ [1..@count]).join(​' '​)

There’s a lot of new syntax here, so let’s go through it one piece at a time.

Each time a new tribble is created, the constructor method runs. (This syntax reflects JavaScript semantics: for any function X, X.prototype.constructor is X.) The constructor sets the isAlive property on the new instance to true and then bumps Tribble.count up by one.

A tribble has two prototypal methods: one to spawn new tribbles and another to remove itself from the population. It’s perfectly kosher to reference the constructor (in this case, Tribble) from prototypal methods, because the constructor will always be defined before they’re called.

In the class body, @ points to the constructor rather than the prototype, and you can define “static” (class-level) properties with the special syntax @key: value (which is equivalent to @key = value). So we’re initializing Tribble.count to be 0 and defining a Tribble.makeTrouble() function. Making count a class-level property rather than a prototype-level one avoids any potential ambiguity over whether an instance’s count is specific to that instance or shared.

Let’s test this:

 tribble1 = ​new​ Tribble
 tribble2 = ​new​ Tribble
 Tribble.makeTrouble() ​# "Trouble! Trouble!"
 Trouble! Trouble!

By instantiating two tribbles, we’ve bolstered Tribble.count to two, so Tribble.makeTrouble’s loop for i in [1..@count] has two iterations. Let’s see if we can bring the count back down:

 tribble1.die()
 Tribble.makeTrouble() ​# "Trouble!"
 Trouble!

Killing off tribble1 again would have no effect, thanks to the unless @isAlive check. And as we know, tribbles are born pregnant, so it won’t be long before the remaining individual repopulates the species:

 tribble2.breed().breed().breed()
 Tribble.makeTrouble() ​# "Trouble! Trouble! Trouble! Trouble!"
 Trouble! Trouble! Trouble! Trouble!

That covers the basics of the class syntax. But much like tribbles, classes are famous for replicating themselves. So let’s close this chapter by introducing the best part of CoffeeScript classes: inheritance.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.90.182