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"}`
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));
}