Can you destructure a JavaScript Object in ClojureScript?
I haven't found a direct way to destructure JS object. You can convert JavaScript object to a ClojureScript datastructure and then destructure:
(let [{:keys [a b]} (js->clj #js {:a 10 :b 20}
:keywordize-keys true)]
(print a)
(print b))
If you don't use :keywordize-keys
option in js->clj
you need to use strs
instead of keys
in the destructuring
(let [{:strs [a b]} (js->clj #js {:a 10 :b 20})]
(print a)
(print b))
Matt Huebert's js-interop library provides JavaScript object destructuring out of the box with its version of let
. All you have to do is add ^:js
in front of the binding form:
(ns foo.bar
(:require [applied-science.js-interop :as j]))
(j/let [^:js {:keys [a b]} #js{:a 10, :b 20}]
[a b])
;; => [10 20]
This applies recursively (there's an escape hatch, ^:clj
) and works in j/fn
and j/defn
as well. These functions act like normal Clojure if the ^:js
is left out.
Associative destructuring is based on get
, which can be mapped onto goog.object/get
for JavaScript objects by extending them to ILookup
:
(extend-type object
ILookup
(-lookup
([o k]
(goog.object/get o (name k)))
([o k not-found]
(goog.object/get o (name k) not-found))))
Even though this results in destructuring working on JavaScript objects, it isn't advisable to extend object
in this way. It would be preferable to decorate an object instance to achieve a similar effect.
Here is an example using reify
:
(defn wrap [o]
(reify
ILookup
(-lookup [_ k]
(goog.object/get o (name k)))
(-lookup [_ k not-found]
(goog.object/get o (name k) not-found))))
With wrap
as defined above:
(let [{:keys [a b]} (wrap #js{:a 10, :b 20})]
(print a)
(print b))
Functions in libraries that offer a capability like wrap
above include:
lookup
in js-interopbean
in CLJS Bean