I would like to nest a number of functions inside a class property as shown below.
Unfortunately, they won’t get access to the main scope of the class.
Can I solve this without passing each nested function a reference to this?
class myClass
constructor: -> @errors = []
doSomething: -> @errors.push "I work as expected"
functions:
doStuff: ->
@errors.push "I cant access @errors" # => TypeError: Cannot call method 'push' of undefined
ugly: (context) ->
context.errors.push "It works, but I am ugly" # Works fine but requires scope injection
Non-working alternative using suggested fat arrow:
class myClass
constructor: ->
@errors = []
@functions:
doStuff: =>
@errors.push "I wont work either" # TypeError: Cannot call method 'toString' of undefined
Optional alternative, which doesn’t write to the global this.errors property:
class myClass
constructor: ->
@functions =
errors: []
doStuff: ->
@errors.push "I will write to functions.errors only"
In JavaScript (as the result, CoffeeScript too), methods use
thisof the object that contains method.This usually works well, unless you deal with example like yours:
When dealing with JavaScript, I would avoid having namespace for functions – it doesn’t play well, even with workarounds. For example, you could try putting reference to
thisobject inobject.functions, so any function inobject.functionswould have access to it.This appears to work at first, but could be confusing when you are using properties like
applyorcallon it,obj1.functions.alsoDoSomething.call(obj2)won’t work as theobj2is not correct object (user should doobj2.functionsinstead which can be confusing).The real solution is: don’t. JavaScript isn’t intended for abuse like this. All object methods should be directly in object prototype. If you have object in it, all methods of it aren’t methods of your object.