In the following code, I was under the impression that using a 'fat arrow' would allow me access to the class variables. Instead, regardless of fat or skinny arrow, I am not able to access the '#accounts' variable.
Any suggestions?
class MyClass
accounts:[]
constructor: (#accounts) ->
($ '.the_buttons').live 'click', bind_clicks
bind_clicks = (event) ->
console.log #accounts
jQuery ->
m = new MyClass([1, 2, 3])
Thanks.
Update
Looks like I had mistyped previously causing a bit of my problem.
Here is code that sort-of does the trick
class MyClass
accounts:[]
constructor: (#accounts) ->
($ '.the_buttons').live 'click', (event) => bind_clicks(event)
bind_clicks: (event) =>
console.log #accounts
jQuery ->
m = new MyClass([1, 2, 3])
However, it feels odd to resort to making the bind_clicks a public method.
You can do that
class MyClass
bind_clicks = (event) ->
console.log #accounts
accounts:null
constructor: (#accounts) ->
($ '.the_buttons').live 'click', bind_clicks
jQuery ->
m = new MyClass([1, 2, 3])
bind_clicks is declared BEFORE the instance methods. It is private. BUT, it is a private class method. It will generate a closure, that's why. I would suggest to use _bind_clicks, the underscore prefix is a common convention to define private methods. Since this doesn't really exist in javascript.
Be careful also when you declare accounts:[], I would suggest accounts:null, more on this: http://html5stars.com/?p=148
Another possible way of doing this. It's pretty similar to yours.
class MyClass
constructor: (#accounts) ->
$('body').live 'click', #bind_clicks
bind_clicks: (event) =>
console.log #accounts
$ ->
m = new MyClass([1, 2, 3])
Don't quote me on this, but I don't think JS has any notion of public/private methods. I supposed if you don't want to expose the method you could do this instead. But you might run the risk or repeating yourself if you use this method more than once.
class MyClass
constructor: (#accounts) ->
$('body').live 'click', (event) =>
console.log #accounts
$ ->
m = new MyClass([1, 2, 3])
Good luck!
Sandro
note: I bounded the events from the body so I could test out the code.
You can make bind_clicks private as follows:
class MyClass
accounts:[]
constructor: (#accounts, #button) ->
bind_clicks = (event) =>
console.log #accounts
#button.click bind_clicks
class Button
click: (#f) ->
do_click: -> #f('event')
button = new Button()
m = new MyClass([1, 2, 3], button)
console.log m.bind_clicks # undefined (private)
button.do_click() # [1, 2, 3]
You can try this out: http://jsfiddle.net/zp6LJ/1/
The private method will have to be defined int he constructor function to achieve what you are looking for.
class MyClass
accounts:[]
constructor: (#accounts) ->
bind_clicks = (event) =>
console.log #accounts
$('.the_buttons').click bind_clicks
jQuery ->
m = new MyClass([1, 2, 3])
Related
I have come across this construct a few times.
Example 1:
_ = require 'underscore'
class Controller extends App
_doSomething: _.throttle (event) ->
$div = $(event.target).closest 'div'
...
My Question:
I have trouble understanding why this construct is valid.
Normally a class function definition goes like:
_doSomething: (event) ->
$div = $(event.target).closest 'div'
...
, 500
So how can _.throttle sit in between : and (event) the function parameter?
If _.throttle is supposed to act as an wrapper, shouldn't it be written as
_doSomething = _.throttle( (event) -> # an anonymous function that takes event as parameter
$div = $(event.target).closest 'div'
...
, 500
Things might be clearer if we add the optional parentheses:
class Controller extends App
_doSomething: _.throttle( (event) ->
$div = $(event.target).closest 'div'
...
)
Now we see that _.throttle is function call and it is being given an anonymous function as its single argument. We can break it down a bit more to further clarify what's going on:
f = (event) ->
$div = $(event.target).closest('div')
...
throttled_function = _.throttle(f)
class Controller extends App
_doSomething: throttled_function
_.throttle returns a function so the code you're looking at just just a complicated version of:
class Controller extends App
_doSomething: some_function
which is nothing special. Keep in mind that you can use anonymous functions when building a class's methods but named functions or other expressions which evaluate to functions serve just as well; the syntax is really:
name: expr
where expr is some expression and f(x) (or _.throttle(some_anonymous_function)) is an expression.
The title says it all. When I use the fat-arrow in CoffeeScript, it stores this first before calling the function. For example:
class myClass
constructor: ->
element = $ "#id"
element.click ->
#myMethod(#value)
return
return
myMethod: (c)->
window.console.log(c)
return
would yield
var myClass;
myClass = (function() {
function myClass() {
var element;
element = $("#id");
element.click(function() {
this.myMethod(this.value);
});
return;
}
myClass.prototype.myMethod = function(c) {
window.console.log(c);
};
return myClass;
})();
Now on line#8 of JavaScript, this.myMethod is wrong. In this scope, this refers to element instead of the class MyClass.
However, if on line#4 of CoffeeScript, I replace element.click -> by element.click => the line#8 in JavaScript will become _this.myMethod(_this.val) where this referring to myClass is stored in _this before calling the function. But _this.value is undefined and even if it were defined, the object I'm trying to access here is element (which is referred to by the actual this keyword in scope of this function).
How would access the actual this now?
You can achieve your goal in at least three ways. The 1st one would be:
class myClass
constructor: ->
element = $ "#id"
element.click =>
#myMethod(element.value)
return
return
myMethod: (c) ->
window.console.log(c)
return
And the 2nd:
class myClass
constructor: ->
element = $ "#id"
myMethodCallback = (c) => #myMethod(c)
element.click ->
myMethodCallback(#value)
return
return
myMethod: (c) ->
window.console.log(c)
return
The 3rd one is as showed below. I'm not sure about jQuery API usage though, so better check on appropriate docs page.
class myClass
constructor: ->
element = $ "#id"
element.click (event) =>
#myMethod(event.target.value)
return
return
myMethod: (c) ->
window.console.log(c)
return
I would prefer the 1st way as it seems to be more straightforward.
This or the other but you need to decide 'which this' you would like to have in scope of the element.click callback. It's not possible to access two 'thises' at the same time.
By the way. All those return statements seems unnecessary. The shortest working solution would look like:
class myClass
constructor: ->
element = $ "#id"
element.click => #myMethod(element.value)
myMethod: (c) -> window.console.log(c)
I have a "class" in coffee script whose instance variables I want to initialize with instance methods that return a value via a callback, but it doesn't work as I had hoped:
EventEmitter = require('events').EventEmitter
class MyClass extends EventEmitter
constructor: ->
#datamember: setDatamember()
setDatamember: ->
someFunction (response) ->
#datamember = response
#emit 'init'
getDatamember: ->
return #datamember
----
myObj = new MyClass
myObj.on 'init', ->
console.log myObj.getDatamember
The result I get suggests that "this" in setDatamember is referring to something different from what "this" refers to in the object instance. If I explicitly call myObj.setDatamember, I get the expected result, but is there any way to call on a set method -- specifically one that sets the data member via a callback -- in the constructor? I've looked through the docs, as well as various other sources of coffeescript info (e.g. this one), and I haven't found anything that touches upon this.
Try using a fat arrow for the anonymous function:
setDatamember: ->
someFunction (response) =>
#datamember = response
#emit 'init'
Also, you'll need to call the correct function in the constructor:
constructor: ->
#setDatamember()
In general, avoid fat arrows on methods - the way Coffee-Script implements this does some bad things to memory usage. Also, it will rarely be necessary.
However, anonymous functions that refer to this will almost always need fat arrows. this is not held in closure like normal variables, and will only be set by binding (Function.prototype.bind) or by calling it as an object method (obj.myMethod() will set this to obj in myMethod).
Try using fat arrows on everything except the constructor:
class MyClass
constructor: ->
#setDatamember()
setDatamember: =>
someFunction (response) =>
#datamember = response
getDatamember: =>
return #datamember
However, you also look to have someFunction in there as an asynchronous function, so you'll never be able to just do
mc = new MyClass
console.log mc.datamember
Because that doesn't wait for someFunction to return before accessing mc.datamember.
Hi I'm new to Js and Coffeescript, here's a situation I feel difficult to refer the property of parent object which is App in the following example
App =
init: ->
this.foo = 'bar'
this.bindEvent()
bindEvent: ->
$('#test').click(this.show)
show: ->
alert this.foo
App.init()
I think the fat arrow may do the trick but once I've changed to show: =>, this in the context of show method refers to the window object, instead of App object that I want to
. Anybody can tell me how to do it right?
http://jsfiddle.net/kZpHX/
When you define your show function, # (AKA this) actually is window so
show: => console.log(#)
will bind show to window. The problem is that you're simply defining an object so there isn't anything to bind to: you aren't defining a class so this is window. You could refer to App explicitly like this:
App =
#...
show: -> alert(App.foo)
Demo: http://jsfiddle.net/ambiguous/3sRVh/
The this.foo in init will do the right thing because saying App.init() sets up the expected this.
You could also hook up the desired this manually:
bindEvent: ->
$('#test').click => #show()
# or
bindEvent: ->
_this = # # JavaScript style
$('#test').click -> _this.show()
Demos: http://jsfiddle.net/ambiguous/byL45/, http://jsfiddle.net/ambiguous/MT8fG/
Or you could create a class for your App instead:
class App
constructor: ->
#foo = 'bar'
#bindEvent()
bindEvent: ->
$('#test').click(#show)
show: =>
console.log(#foo)
new App
That way your show: => will behave the way you expect it to.
Demo: http://jsfiddle.net/ambiguous/byatH/
I want to create objects in Ruby style with CoffeeScript. So I want to do something like
class A
constructor: (#params) ->
a = new A {send: true, name: "fit"}
a.send #true
Is there any "standard" way to do this?
There is no way to do it directly. You could define a base class that has code to do it, like such
class Base
constructor: (props) ->
for key, value of props
#[key] = value
class Extend extends Base
constructor: (props) ->
super props
alert "#{#key1}, #{#key2}"
e = new Extend 'key1': 'val1', 'key2': 'val2'
alert "#{e.key1}, #{e.key2}"
See it working here