In a fat arrowed function of a coffeescript class, how can I access the scope of the class as well as the function?
Example:
class Example
foo: ->
$('.element').each => # or ->
#bar($(this)) # I want to access 'bar' as well as the jquery element
bar: (element) ->
element.hide()
So in this example, if I use a => then the # refers to the this of the class but the 'this' is then wrong, whereas if I use a -> for the each, then the 'this' is correctly scoped but but then how do I reference the class function bar?
Thanks!
While mak is right, he fails to point out that in coffee script you rarely need jQuery's each method, which as you noticed, punches your execution context in the face without your permission.
class Example
foo: ->
for element in $('.element')
#bar $(element)
bar: (element) ->
element.hide()
Coffee script's looping features support the concept of each without any actual custom library code at all. And they also do not generate a new scope or context meaning you dont need a fat arrow of any kind.
That's because in CoffeeScript # is an alias for this i.e. when you compile your .coffee to .js # will be replaced with this.
If Example::bar is ugly, I don't think there are 'prettier' solutions.
You can store a reference to this before calling .each:
class Example
foo: ->
self = #
$('.element').each ->
self.bar($(this)) # or self.bar($(#))
bar: (element) ->
element.hide()
After checking different solution. Here something appear for me as the most complete sample with each and click :
class MainApp
self = []
constructor: ->
self = #
toDoOnClick: (event) ->
self.bar($(event.target)) #hide the clicked object
bar: (element) ->
element.hide()
sampleMethod:->
$(".myDiv").click (e) -> self.toDoOnClick(e)
$('.element').each ->
self.bar($(this))
Related
I'm new to F# and I'm trying to implement a little calculator with these interfaces...
But I'm struggling with the derive part as soon as i get to f_add.
Would be nice if someone could help me out. :)
type IFunction =
interface
abstract member ToString: Unit -> String
abstract member Apply: Nat -> Nat
abstract member Derive: Unit -> IFunction
end
Since f_add is defined in curried form (typical for F# functions), and not tupled, you need to pass the arguments with spaces, not as a tuple:
// HERE . Using comma makes that a tuple
// member self.Derive () = f_add(f.Derive (), g.Derive ()) //wrong
Instead, pass as an F# style function:
member self.Derive () = f_add (f.Derive ()) (g.Derive ())
The same issue exists in the other implementations.
For code reuse purpose I want to capture some logic in a single function and have it called in other modules
Here is the function definition
// Module A
define (require) ->
doSomething(a, b, c) ->
"#{a}?#{b}&#{c}"
And here is how the funciton doSomething is used
// Module B
define(require) ->
a = require 'A'
...
class Bee
constructor: ->
#val = a.doSomething(1, 2, 3)
However in the browser, I got this error message
Uncaught ReferenceError: doSomething is not defined
What is the proper way to export/import a free function in coffeescript?
This:
define (require) ->
doSomething(a, b, c) ->
"#{a}?#{b}&#{c}"
isn't a function definition. That is really this in disguise:
define (require) ->
return doSomething(a, b, c)( -> "#{a}?#{b}&#{c}")
so your module is trying to call the doSomething function and then call what it returns as another function which takes a third function as an argument. Then whatever doSomething(...)(...) returns is sent back from the module.
So when you say this:
a = require 'A'
you're getting "who knows what" in a and that thing doesn't have a doSomething property so a.doSomething(1,2,3) gives you a ReferenceError.
I think you want to wrap your function in an object in your module:
define (require) ->
doSomething: (a, b, c) ->
"#{a}?#{b}&#{c}"
Alternatively, you could just return the function:
define (require) ->
(a, b, c) ->
"#{a}?#{b}&#{c}"
and then use it like this:
doSomething = require 'A'
doSomething(1, 2, 3)
Consider the following classes:
class A
constructor: ->
#nestedA = new NestedA()
class NestedA
constructor: ->
#NestedA = NestedA
#A = A
class B
constructor: ->
#nestedB = new NestedB()
class NestedB
constructor: ->
#NestedB = NestedB
#B = B
In this way, classes A and B are available in the global namespace, and NestedA and NestedB are only available through the A and B namespaces, respectively. I like this approach, but this can lead to the separate coffeescript files getting rather large. Thus I was wondering whether there was a way to separate the classes (NestedA and NestedB) into separate coffeescript files and still maintain the namespaces?
You could use RequireJS to load NestedA.coffee as a dependency into A.coffee (and do the same for the Bs). And then use RequireJS to load A.coffee into your main application in the same way.
Class A
#NestedA = require('cs!NestedA)
This should work but it might be a bit of an architectural shift if you are not already using RequireJS.
I would do it this way. This approach is very similar to what TypeScript does, but the pattern fits just as well in CoffeeScript.
#a.coffee
A = do (A = A ? {})->
class Foo
constructor: ->
#nestedFoo = new NestedFoo()
class NestedFoo
constructor ->
greet: ->
console.log('Hello World')
#exports
A.Foo = Foo
A.NestedFoo = NestedFoo
A
#somwhere-else.coffee
foo = new A.Foo()
foo.nestedFoo.greet() #yields 'Hello World'
This approach has the advantage that you can add as many other features to the namespace from whatever other files you want.
CoffeeScript has the handy do statement to preserve variables in a closure. But how do I preserve properties of this with do? That always seems to fail.
Example: in a class method I want to attach an event handler to an HTML element using jQuery. The handler should call another method of the same class with a parameter. Now if I write:
foo = getBar()
$('div').click -> #handler foo
this will obviously not work, because the function will be executed in a different context that doesn't have a method named handler. However, if I use do and I write this:
foo = getBar()
do (#handler, foo) ->
$('div').click -> #handler foo
that will also fail, since #handler translates to this.handler which does not make it through the closure. What's an elegant way to solve this?
Try using a fat arrow (equals sign)
foo = getBar()
$('div').click => #handler foo
Or, get a reference to handler before your callback.
cbHandler = #handler
foo = getBar()
$('div').click -> cbHandler foo
How would you extend a class using CoffeeScript, but have the construction arguments passed to super?
Eg:
class List extends Array
# Some other stuff to make it work...
list = new List(1,2,3)
console.log list
[1, 2, 3]
In general, this would work without additional code; the parent constructor is used unless expressly overridden:
class A
constructor: ->
console.log arg for arg in arguments
class B extends A
new B('foo') # output: 'foo'
And the problem isn't that Array doesn't have a constructor method:
coffee> Array.constructor
[Function: Function]
The problem is just that Array is just plain weird. While arrays are "just objects" in principle, in practice they're stored differently. So when you try to apply that constructor to an object that isn't an array (even if it passes the instanceof Array test), it doesn't work.
So, you can use Acorn's solution, but then you may run into other problems down the road (especially if you pass a List to something that expects a true array). For that reason, I'd recommend implementing List as a wrapper around an array instance, rather than trying to use inheritance from a native object type.
While we're on the subject, one very important clarification: When you use super by itself, that does pass all arguments! This behavior is borrowed from Ruby. So
class B extends A
constructor: ->
super
will pass along all arguments to A's constructor, while
class B extends A
constructor: ->
super()
will invoke A's constructor with no arguments.
class List extends Array
constructor: ->
#push arguments...
toString: ->
#join('-')
list = new List(1, 2)
list.push(3)
list.toString()
=>
'1-2-3'
Using extends in CoffeeScript expects the superclass to be in CoffeeScript too. If you're using a non-CS class, e.g. Array in the original question, then you may encounter problems.
This solved the general case for me. It's a bit of a hack because it uses _super which probably isn't intended to be used in the compiled JS.
class MyClass extends SomeJsLib
constructor: ->
_super.call #, arg1, arg2
Or if you just want to pass thru arguments from the caller:
class MyClass extends SomeJsLib
constructor: ->
_super.apply #, arguments
In my exploration of javascript I required a generic way to create a class with a dynamic number of constructor arguments. As mentioned this won't work for array as far as I know, it will only work for coffee-script style classes.
Calling a specific function with a dynamic number of arguments is easy enough through .apply
args = [1, 2, 3]
f = measurement.clone
f.apply measurement, args
A class can extend a class saved in a variable. As a result we can write a function that returns new sub-classes.
classfactory = (f) ->
class extension extends f
Putting it all together we can create a function that returns new sub-classes in which we apply arguments to the super class's constructor.
classwitharguments = (f, args) ->
class extension extends f
constructor: () ->
extension.__super__.constructor.apply #, args
To use this new factory
args = [1, 2, 3]
instance = new (classwitharguments Measurement, args)
Thoughts? Comments? Suggestions? Limitations I didn't think about? Let me know.