ClojureScriptのオブジェクトからJavaScriptのオブジェクトに変換する方法として#js
とclj->js
がありますが、その違いは何でしょうか?
(identity #js [[[1 2]]])
(clj->js [[[1 2]]])
#js
はvectorとmapのみ変換可能で、再帰的には適用されません。
clj->js
はlistやsetも変換可能で、再帰的に適用されます。
コードを見るとそれがよくわかります。
#js
は以下のread-js
が本体です。
reader.cljs抜粋
(defn ^:private read-js
[form]
(cond
(vector? form)
(let [arr (array)]
(doseq [x form]
(.push arr x))
arr)
(map? form)
(let [obj (js-obj)]
(doseq [[k v] form]
(aset obj (name k) v))
obj)
:else
(reader-error nil
(str "JS literal expects a vector or map containing "
"only string or unqualified keyword keys"))))
clj->js
は以下です。keywordやsymbolも変換されるようです。
core.cljs抜粋
(defn clj->js
"Recursively transforms ClojureScript values to JavaScript.
sets/vectors/lists become Arrays, Keywords and Symbol become Strings,
Maps become Objects. Arbitrary keys are encoded to by key->js."
[x]
(when-not (nil? x)
(if (satisfies? IEncodeJS x)
(-clj->js x)
(cond
(keyword? x) (name x)
(symbol? x) (str x)
(map? x) (let [m (js-obj)]
(doseq [[k v] x]
(aset m (key->js k) (clj->js v)))
m)
(coll? x) (let [arr (array)]
(doseq [x (map clj->js x)]
(.push arr x))
arr)
:else x))))