I found myself in a situation where coffeescript was complaining that Object has no method foo when it clearly did. What is going on? Why is it so hard to call a class method from within a class?
class Car
get_in_accident: ->
@honk_horn("panic")
@airbag()
airbag: ->
console.log("imma deploying mah airbag!")
# just showing here that arguments don't change anything
honk_horn: (level) ->
if (level == "pissed")
console.log("HONK HONK")
else if (level == "panic")
@yell("aaaa!", 1000)
console.log("HON...")
# the real issue is callbacks that lose the original scope
yell: (message, wait_time) ->
setTimeout ->
console.log(message)
@honk_horn("pissed")
console.log("You jerk!")
, wait_time
car = new Car
car.get_in_accident()
What you see in this example is: ` HON… imma deploying mah airbag! aaaa!
timers.js:103 if (!process.listeners(‘uncaughtException’).length) throw e; ^ TypeError: Object # has no method ‘honk_horn’ at Object._onTimeout (.:29:14) at Timer.list.ontimeout (timers.js:101:19) `
@honk_horn is supposed to refer to the instance variable when yell is called. It doesn’t know about it’s self? Well, there’s a good chapter about this (Chapter 6 of this book) on Binding and the Fat Arrow in coffeescript. It’s a simple fix to a confusing problem. The method that is called later (the callback method) needs to have a fat arrow => which generates a __bind function in javascript when the coffescript is compiled. This saves you a lot of time and effort. All you have to remember is to use the fat arrow when a callback is going to be called out of scope.
So just change the setTimeout line to have a => instead of ->:
yell: (message, wait_time) ->
setTimeout =>
Now it works right. Also notice that the “aaaa!” yell is happening before the “HON…” log statement in both examples. ` HON… imma deploying mah airbag! aaaa! HONK HONK You jerk! `