Skip to content

Instantly share code, notes, and snippets.

@pesterhazy
Last active February 26, 2024 20:18
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pesterhazy/82494dc329b403288abc2491272ee05c to your computer and use it in GitHub Desktop.
Save pesterhazy/82494dc329b403288abc2491272ee05c to your computer and use it in GitHub Desktop.
ClojureScript Do's and Don'ts: clj->js

ClojureScript Do's and Dont's: clj->js

You should prefer

#js["tag" #js{"k1" v1, "k2" v2}]

over

(clj->js ["tag" {"k1" v1, "k2" v2}])

Why? clj->js is a function that recursively turns any CLJS data structure into the corresponding Plain Old JavaScript data (i.e. arrays and js-objs). It transforms the data structure at runtime.

By contrast, the literals #js{} and #js[] cause the ClojureScript compiler to emit JavaScript literal (["tag" {"k1":"v1","k2":"v2"}]) in the compiled output directly. This happens at compile time, so you don't pay a performance penalty at runtime. In many cases, you also don't need, or want, a recursive transformation of nested data structures.

With that in mind, when should you use clj->js instead of object and array literals? Two cases come to mind:

  • You're transforming dynamically generated immutable data structures (but cf. the into-array and js-obj functions)
  • You're working with data from an exteneral source such as a network request or a library function returning arbitrarily nested data structures (but consider using transit)

In any case, when using #js[] and #js{} keep in mind that with nested data you will need to repeat the #js prefix:

;; This creates a JS array containing a PersistentArrayMap, which is probably not what you want:

#js[{:k "v"}]

;; This creates a JS array containing a plain JS object:

#js[#js{:k "v"}`

A look a the compiled code

cljs.user=> (defn foo [] #js {:foo "bar"})

cljs.user=> (print (.toString foo))

function cljs$user$foo(){
return ({"foo": "bar"});
}

cljs.user=> (defn foo2 [] (clj->js {:foo "bar"}))
cljs.user=> (print (.toString foo2))

function cljs$user$foo2(){
return cljs.core.clj__GT_js.call(null,new cljs.core.PersistentArrayMap(null, 1, [new cljs.core.Keyword(null,"foo","foo",1268894036),"bar"], null));
}

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment