Clojure Constructs and Techniques to Interact with JavaScript

Clojure lets you write code close to the metal ie the host language. In this chapter, we'll learn about constructs and techniques to interact with JavaScript within Clojure.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Tinycanva: Clojure for React Developers course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Tinycanva: Clojure for React Developers, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Tinycanva: Clojure for React Developers
  • [00:00 - 00:07] Closure doesn't hide the underlying host from the developer. It lets you bypass Closure and write code close to the metal.

    [00:08 - 00:15] This chapter on Interop is focused on JavaScript as the host language. But most of the concepts will apply to other hosts too.

    [00:16 - 00:27] The code examples in this chapter are in the first project.interop namespace. JavaScript objects like array, date, math, and others are accessible in the JS namespace.

    [00:28 - 00:35] You can evaluate these forms and check what they look like. In a browser environment, you can access the window object using JS/window.

    [00:36 - 00:47] To create instances of JS objects, we can use the new function or the dot operator. All arguments passed to the new operator are passed to the JS constructor.

    [00:48 - 00:58] Notice the hash.js prefix in the result of the inline evaluation. This signifies that the data structure is not a CLJS vector but a JS array.

    [00:59 - 01:10] You can use Clips app to check the transpilation in real time. A method bar on object foo can be called using dot bar foo with arguments pqr.

    [01:11 - 01:22] This is equivalent to calling foo dot bar pqr in the JS domain. The now method on the JS date is a static function i.e. does not require an initialized object.

    [01:23 - 01:29] The map method on JS array is an instance method. i.e. requires an instance of array to operate on.

    [01:30 - 01:43] A static method bar defined on class foo can be alternatively called using the JS foo dot bar syntax. A property bar on object foo can be accessed using hyphen dot bar foo.

    [01:44 - 01:57] For example, if you'd like to access the static property name of JS object, you can do something like this. In some cases where static property is deeply nested, your code might feel less readable.

    [01:58 - 02:09] For example, if you want to pull out the value of a target of an event, you'd have to write something like this. In cases like this, we can use the double dot function to access these deeply nested properties.

    [02:10 - 02:25] Closure data structures can be converted from and to native JS data structures. This is helpful if you are using an NPM module that expects JS data structures or if you choose to write JavaScript inside closure for performance enhancements.

    [02:26 - 02:38] To helper functions, clj to js and js to clj ate the conversion. While using js to clj, the keys of the js objects show up as strings in the clj snap.

    [02:39 - 02:49] If you prefer keywords instead, you can pass an additional argument to keyword ize the keys. Java and JavaScript allow you to write mutable code.

    [02:50 - 03:02] For example, you might have a UI element and can call some function on it to set some properties. Like in this example, we instantiate an imaginary rectangle class and call some methods on it.

    [03:03 - 03:12] All these operations mutate the internal state of rect object. If we were to write the same using cljs interrupt, we'd end up with something like this.

    [03:13 - 03:20] With the dutomacro, we can rewrite the same as follows. You might be wondering that dutom looks similar to the thread first macro.

    [03:21 - 03:27] However, these macros are different and a common source of confusion. Closure is inherently immutable.

    [03:28 - 03:35] The threading macro does not mutate the form in the previous step. The end result of the threading macro is the result of the last form.

    [03:36 - 03:45] Dutom however mutates the first form. The result of a dutomacro is the first form after the mutations have been applied.

    [03:46 - 03:52] The interrupt syntax is powerful enough to access the host functionality. But it comes at the cost of readability.

    [03:53 - 04:08] Although interrupt is idiomatic enclosure, it is not as natural as closure's native data structures. In cases where you rely heavily on interrupt, you can use dedicated libraries that make the interrupt more closure rescue.

    [04:09 - 04:15] There are many interrupt libraries, but you should definitely be aware of two of them. These are promissor and jsinterop.

    [04:16 - 04:25] Promissor allows for native interaction with js promises. And jsinterop is a general purpose closure library for manipulation of js data structures.

    [04:26 - 04:45] We learned how to access the host language constructs directly from closure, study data types and macros that make interrupt code more readable. After having written closure on the JVM and JavaScript for multiple years, I realized that one needs to know both the host and closure to be productive.

    [04:46 - 04:58] You will at some point of time reach a bottleneck due to the decisions made by the host and will have no choice but to code close to the metal. This is a non-issue however since closure's interrupt is fairly capable.

    [04:59 - 05:08] This chapter wraps up our discourse on closure standard library. The fundamentals we covered will help us as we start building the tiny Kanwa project in the next module.