如何将 (var a in b) 的 JavaScript 深度映射到 ClojureScript?

How to deep map JavaScripts for (var a in b) to ClojureScript?

此代码似乎将对象视为一组键值对:

for (var a in b) { ...

我想将它映射到 ClojureScript

现在通常我可以这样做:

(doseq [[k v] (js->clj js/b)]

问题是 b 包含嵌套映射 - 而 js-clj 很浅。

另一个问题是对象中的键是整数 - 因此无法通过字段值访问键。即

{0 #object... 1 #object ... }

我的问题是:如何将 JavaScript for (var a in b) 深度映射到 ClojureScript?

(doc js->clj)

-------------------------
cljs.core/js->clj
([x] [x & opts])
  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.

如您所见,js-clj 将 JS 对象 递归地 转换为 ClojureScript 数据结构。

所以当你有一个 JS 对象时:

{1: {2: "a"}, 3: [true, 4]}

js->clj 会将其转换为以下 ClojureScript 对象:

{"1" {"2" "a"}, "3" [true 4]}

据我所知,当您使用 for 遍历 JS 对象属性时,它将仅遍历您传递的对象的属性,它不会深入到这些属性的属性中:

for (a in {1: {2: "a"}, 3: {4: "b"}) { console.log(a); };

它只会打印 13 而不会打印到 24.

所以那个 for 循环的 ClojureScript 版本是:

(doseq [[k v] (js->clj js/g)]
  (.log js/console k))

所以我不明白为什么你说 js->clj 很肤浅,但事实并非如此。

如果您想递归地遍历整个数据结构,那么您可以使用 clojure.walk/prewalkclojure.walk/postwolk 来访问数据结构中的所有值(它知道如何进入地图,向量、集合等)并为它遇到的每个值调用你的函数:

(clojure.walk/postwalk
  #(do (.log js/console "PostWalking" %)
       %)
  {:a 1 :b {:c 2}})

(clojure.walk/prewalk
  #(do (.log js/console "PreWalking" %)
       %)
  {:a 1 :b {:c 2}})