(defn domready [handler]
(.addEventListener js/window "DOMContentLoaded" handler))
I borrowed this code from here. The problem is I don't totally understand what's going on. JS interop is still a bit of a mystery to me.
.addEventListener
So this is clearly a procedure call, but it's kind of generic. It's like Clojurescript took everything that was inside an object, took it out, and you use it to call that method on "objects". As long as that "object" has the ".addEventListener" property it will call this. Is that what it's doing? Why not use a keyword instead? like (:addEventListener domElement)
that seems more logical to me.
js/window
What is this? Is it a namespace or an object? Are they the same thing?
"DOMContentLoaded"
A string, that's familiar.
handler
Also familiar, but does it have a notion of this
? Not that I'm really going to miss this
.
.addEventListener
So this is clearly a procedure call, but it's kind of generic. It's like Clojurescript took everything that was inside an object, took it out, and you use it to call that method on "objects". As long as that "object" has the ".addEventListener" property it will call this. Is that what it's doing? Why not use a keyword instead? like (:addEventListener domElement) that seems more logical to me.
Your mental model about how this works is mostly fine. What it does when it compiles is move the function name to be run as a method on the first argument.
(.method obj ...args)
get's transformed to obj.method(...args)
This type of interop comes from the parent language Clojure.
On why do we have an explicit version of calling the function that's not Clojure idiomatic, I think the idea is to have clear separation between what is native Clojure code with Clojure semantics (immutability, friendly to CLJ data structures, etc) and what is interoperating with the host environment (mutable, not friendly to CLJ data structures, etc).
In my opinion it is better to have clear separation between those two given how different the semantics of CLJS and the host platforms are. For me explicitness is better than implicit in this case (it is easy to spot looking at the code what is JS code in CLJS, and what is pure CLJS).
js/window
What is this? Is it a namespace or an object? Are they the same thing?
Both, js/
is accessing the namespace js
, which is where CLJS puts the JS namespace (since there is only one and global). window
is just grabbing the window
variable from the js namespace.
This is no different from how you access variables in other namespaces in CLJS. If you (def a 1)
in (ns cljs.test)
and then run cljs.test/a
that will give you 1
. Same form, ns/something-in-that-ns
.
"DOMContentLoaded"
A string, that's familiar.
\o/
handler
Also familiar, but does it have a notion of this? Not that I'm really going to miss this.
Not sure what this
has to do with handler
. It is just a higher order function passed into domready
as a parameter, like you would do in JS: function domready (onReady) { window.addEventListener("DOMContentLoaded", onReady) }
I hope this helps, if you want to try it out live and learn some more, maybe visit the Talking with JS on the Diving into ClojureScript tutorial, or maybe check this section of the lt-cljs-tutorial.
I'm just learning clojurescript so I don't really know if it is the correct answer but I've done it in the following way:
(defn handler [] (js/console.log "ready"))
(js/document.addEventListener "DOMContentLoaded" handler)
which is then translated to
cljs.user.handler = (function cljs$user$handler(){
return console.log("ready");
});
document.addEventListener("DOMContentLoaded",cljs.user.handler);
to check how clojurescript translate code I've used KLIMPSE http://app.klipse.tech/
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