2015-09-08 13 views
7

Ich versuche ein Javascript-Objekt in ein Clojure zu konvertieren. Ich erhalte jedoch den folgenden Fehler:ClojureScript - beliebiges JavaScript-Objekt in Clojure-Script-Map konvertieren

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

Ja, dieses Objekt stammt aus der Geolocation API. Ich nehme an, dass ich IEncodeClojure und IWriter verlängern muss, aber ich habe keine Ahnung wie.

Zum Beispiel Hinzufügen des folgenden:

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

ergibt einen Fehler, wenn mein Code Laden: Uncaught TypeError: Cannot read property 'prototype' of undefined

+0

Sind Sie sicher, dass Sie ein Objekt dort haben und nicht 'undefined'? Was ergibt '(js/console.log (undefined? E))? –

+0

@TimPote Es ist nicht undefiniert: benutze Clojure Timbre, ich bekomme den Namen des Objekts. Mit js/console.log bekomme ich das gleiche js-Objekt, wenn ich '(js/console.log e)' und '(js/console.log (js-> clj e))' mache. – nha

Antwort

4

Die akzeptierte Antwort nicht für mich mit dem Javascript-Objekt window.performance.timing arbeitet. Dies liegt daran, dass Object.keys() die Requisiten für das Objekt PerformanceTiming nicht tatsächlich zurückgibt.

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

Dies ist trotz der Tatsache, dass die Requisiten von PerformanceTiming sind in der Tat iterable mit Vanille JavaScript-Schleife:

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

Das folgende ist, was ich kam mit einem beliebigen JavaScript-Objekt zu einem ClojureScript konvertieren Karte. Beachten Sie die Verwendung von zwei einfachen Google Closure-Funktionen.

  • goog.typeOf wickelt typeof, die uns in ClojureScript normalerweise nicht zugänglich ist. Ich benutze das, um Requisiten herauszufiltern, die Funktionen sind.
  • goog.object.getKeys Wraps for (prop in obj) {...}, Aufbau eines Array-Ergebnis, das wir in eine Karte reduzieren können.

Lösung

(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))))