What am I doing wrong here? I'm using the fat arrows => for my callbacks, however when the code reaches cb.onEndElement and calls @returner I get an null object exception. So why doesn't @returner exist?
class Parser
constructor: () ->
@returner = (data) ->
searchParser: new xml.SaxParser (cb) =>
cb.onStartElementNS (elem, attrs, prefix, url, ns) =>
if elem is "results" then @results = []
else if elem is "title" then @curr = "title"
else @curr = "none"
cb.onCdata (cdata) =>
if @curr is "title" then @book.title = cdata
cb.onEndElementNS (elem, prefix, url) =>
@results.push @book if elem is "book"
cb.onEndDocument =>
@returner @results
search: (str, callback) ->
@returner = callback
@searchParser.parseString str
p = new Parser
p.search "somexml", (data) ->
console.log JSON.stringify data
First off, the concept you're talking about isn't "scope"—it's
this
, also informally called the "context." And it's certainly one of the trickiest concepts in JavaScript (and thus CoffeeScript), even though the rules are fairly simple. Perhaps it's because the wordthis
itself, which doesn't seem like its meaning should be so easily changed depending on how a function is called...Nicholas' answer is dead-on, but I recommend that you also read up on
this
and try to really understand it, rather than just using=>
all the time (it's a great tool, but not always the right one). A few resources I recommend:this
this
?this
, as well as scope, in a fair amount of depth)Your method
search
needs a fat-arrow=>
in order to bind it to instances ofParser
.Additionally, although the line
searchParser: new xml.SaxParser (cb) =>
compiles, it's probably not doing what you want, because the fat arrow is binding the callback toParser
and notthis
. You have two options:@searchParser = new xml.SaxParser (cb) => ...
in your constructor instead, given the way you are calling it.searchParser: () => new xml.SaxParser (cb) =>
and call it with parens lower down:@searchParser().parseString str
, which would create asearchParser
method bound tothis
As an example, here are my two solutions, as well as your original line, slightly simplified, as well as the compiled code, for compare and contrast purposes:
Simplified example in CoffeeScript:
Compiled JavaScript:
Note how
searchParser1
andsearchParser2
have their callbacks bound tothis
andsearchParser
's is bound toParser
.As always, the "Try CoffeeScript" button at the CoffeeScript homepage (http://jashkenas.github.com/coffee-script/) is your friend!