9

Is there a simple way to list the properties and functions of a JavaScript object in ClojureScript?

I've tried the following:

(keys (js->clj (.getContext canvas "2d")))

But this throws the following error:

ExceptionInfo #<Error: [object CanvasRenderingContext2D] is not ISeqable>  clojure.core/ex-info (core.clj:4591)

2 Answers 2

16

I figured out a way. You can just call

(js-keys (.getContext canvas "2d"))

and that will list all functions and properties of the JavaScript object.

Sign up to request clarification or add additional context in comments.

1 Comment

I think it's working => app.klipse.tech/…
5

You are calling keys clojure function, which returns keys of a (clojure) map. To return all properties of javascript object you should do this :

(.keys js/Object myObject)

which is the analogy of javascript code :

Object.keys(myObject);

Edit : I just looked into the source of js->clj - https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/core.cljs and I also tried it with canvas context. The problem is that the canvas context isn't a standard js/Object and therefore condition (identical? (type x) js/Object) is not satisfied and the js->clj function ends up in the else branch, which makes js->clj behave as identity function, which means that it just returns the context as you pass it in.

This is the source code :

(defprotocol IEncodeClojure
  (-js->clj [x options] "Transforms JavaScript values to Clojure"))

(defn js->clj
  "Recursively transforms JavaScript arrays into ClojureScript
   vectors, and JavaScript objects into ClojureScript maps.  With
   option ':keywordize-keys true' will convert object fields from
   strings to keywords."
 ([x] (js->clj x {:keywordize-keys false}))
 ([x & opts]
   (let [{:keys [keywordize-keys]} opts
      keyfn (if keywordize-keys keyword str)
      f (fn thisfn [x]
          (cond
            (satisfies? IEncodeClojure x)
            (-js->clj x (apply array-map opts))

            (seq? x)
            (doall (map thisfn x))

            (coll? x)
            (into (empty x) (map thisfn x))

            (array? x)
            (vec (map thisfn x))

            (identical? (type x) js/Object)
            (into {} (for [k (js-keys x)]
                       [(keyfn k) (thisfn (aget x k))]))

            :else x))]
       (f x))))

3 Comments

If you also want the properties from the prototype chain, see goog.object.getKeys.
I am calling keys on the result of the js->clj function, which, according to the documentation, transforms JavaScript objects into ClojureScript maps. Why does that not work?
Sorry, not the best answer. However I looked into the js->cljs function and your case and I found what the problem is. I updated the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.