Search code examples
clojurescript

Can you destructure a JavaScript Object in ClojureScript?


I was wondering if there was a way to get ClojureScript destructuring to work with JavaScript objects, such as:

(let [{:keys [a b]} #js{:a 10, :b 20}]
  (print a)  ;=> I get nil, but I'd want to get 10
  (print b)) ;=> I get nil, bu I'd want to get 20

Thank You


Solution

  • 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: