ClojureScript - преобразовать произвольный объект JavaScript в Clojure Script карту

Я пытаюсь преобразовать объект Javascript в Clojure. Однако я получаю следующую ошибку:

(js/console.log (js->clj e)) ;; has no effect
 (pprint (js->clj e)) ;; No protocol method IWriter.-write defined for type object: [object Geoposition]

Да, этот объект исходит из API геолокации. Я полагаю, что мне нужно расширить IEncodeClojure и IWriter, но я не знаю, как это сделать.

Например, добавив следующее:

(extend-protocol IEncodeClojure
 Coordinates
 (-js->clj [x options]
 (println "HERE " x options)))

Устанавливает ошибку при загрузке моего кода: Uncaught TypeError: Cannot read property 'prototype' of undefined

2 ответа

js->clj работает только для Object, все с пользовательским конструктором (см. type) будет возвращено как есть.

см. ниже: https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/core.cljs#L9319

Я предлагаю сделать это вместо:

(defn jsx->clj
 [x]
 (into {} (for [k (.keys js/Object x)] [k (aget x k)])))


Принятый ответ не работал у меня с javascript-объектом window.performance.timing. Это связано с тем, что Object.keys() фактически не возвращает реквизиты для объекта PerformanceTiming.

(.keys js/Object (.-timing (.-performance js/window))
; => #js[]

Это несмотря на то, что реквизиты PerformanceTiming действительно являются итерабельными с помощью цикла ванильного JavaScript:

for (a in window.performance.timing) {
 console.log(a);
}
// navigationStart
// unloadEventStart
// unloadEventEnd
// ...

Следующее - это то, что я придумал для преобразования произвольного объекта JavaScript в карту ClojureScript. Обратите внимание на использование двух простых функций Google Closure.

  • goog.typeOf wraps typeof, который обычно не доступен нам в ClojureScript. Я использую это, чтобы отфильтровать реквизиты, которые являются функциями.
  • goog.object.getKeys wraps for (prop in obj) {...}, создавая результат массива, который мы можем свести к карте.

Решение

(defn obj->clj
 [obj]
 (-> (fn [result key]
 (let [v (aget obj key)]
 (if (= "function" (goog/typeOf v))
 result
 (assoc result key v))))
 (reduce {} (.getKeys goog/object obj))))

licensed under cc by-sa 3.0 with attribution.