I'm trying to access an instance method inside of a map
call, unfortunately my reference to the instance object is being redefined to Window. I'm not sure how to get a hold of my instance method:
class Test
constructor: (@an_array) ->
f: () ->
@an_array.map (value) ->
@a(value)
a: (value) ->
alert value
t = new Test [1, 2, 3]
t.f() // TypeError: Object [object Window] has no method 'a'
Here's a functional link to the above code
There are various ways to deal with this.
The most common in CoffeeScript would be to use a fat arrow (=>
) to produce a bound function:
@an_array.map (value) => @a(value)
Demo: http://jsfiddle.net/ambiguous/6BW8q/
The standard JavaScript approaches will also work (and sometimes would be necessary or more appropriate):
Save a reference to @
so that you don't have to care what this
is inside the callback function:
_this = @
@an_array.map (value) -> _this.a(value)
Demo: http://jsfiddle.net/ambiguous/XhP4z/
I tend to use _this
instead of self
as the name for this thing due to the existence of window.self
and the interesting bugs that causes if you forget the var
in JavaScript.
Manually create a bound function using Function.bind
, this isn't quite universally supported though:
@an_array.map ((value) -> @a(value)).bind(@)
Demo: http://jsfiddle.net/ambiguous/n2XnC/
Use jQuery's $.proxy
, Underscore's _.bind
, or some other non-native bound function implementation:
@an_array.map _((value) -> @a(value)).bind(@)
Demo: http://jsfiddle.net/ambiguous/LAy9L/
Which one you choose depends on your environment and specific needs:
=>
so you'll need to use some variant of (2) or (3) above (or possibly Function.call
or Function.apply
).this
at the same time then you'd go with (1).bind
exists then you' probably end up with (3) and which branch of (3) would probably depend on which library you already have available.Figured out that I can do it by defining a variable to hold my reference to this
:
class Test
constructor: (@an_array) ->
f: () ->
self = @
@an_array.map (value) ->
self.a(value)
a: (value) ->
alert value
t = new Test [1, 2, 3]
t.f() // raises 3 alerts: 1, 2, 3
Here's a working example.
This feels like a bit of a hack, so I'll leave the Q&A up for someone to school me in how this should be done. :D
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With