2024 年 Clojure 状态调查 中分享您的想法!

欢迎!请参阅 关于页面 了解更多有关其工作原理的信息。

+3
ClojureScript

版本:1.9.946
来自问题 CLJS-1998 的后续问题

`
cljs.user=> (js->clj #js {})
{}

cljs.user=> (js->clj (.create js/Object null))

对象[对象]

cljs.user=> (keys (js->clj (.create js/Object null)))
org.mozilla.javascript.EcmaError: TypeError: Cannot find default value for object. (.cljs_rhino_repl/goog/../.cljs_rhino_repl/cljs/core.js#9915)

 (.cljs_rhino_repl/cljs/core.cljs:2930:10)
 cljs$core$seq (.cljs_rhino_repl/cljs/core.cljs:1212:13)
 cljs$core$keys (.cljs_rhino_repl/cljs/core.cljs:8648:3)
 (NO_SOURCE_FILE <cljs repl>:1:0)
 (NO_SOURCE_FILE <cljs repl>:1:0)

`

5 个答案

0

评论者:kurtharriger

为了更全面的背景,使用第三方库生成的具有空原型的对象源在此处 https://github.com/ProseMirror/prosemirror-model/blob/cdded3d/src/schema.js#L13

0

评论者:kurtharriger

(def a (.create js/Object null)) => #'cljs.user/a (type a) => nil

js->clj 的实现明确检查类型 js/Object。

`
(defn js->clj
"递归地将 JavaScript 数组转换为 ClojureScript 向量,将 JavaScript 对象转换为 ClojureScript 映射。使用 ':keywordize-keys true' 选项将对象字段从字符串转换为关键字。)



((link: x) (js->clj x :keywordize-keys false))
((link: x & opts)

(let (link: {:keys [keywordize-keys)} opts
      keyfn (if keywordize-keys keyword str)
      f (fn thisfn (link: 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 (link: k (js-keys x))
                       (link: (keyfn k) (thisfn (unchecked-get x k)))))

            :else x))

`

我认为也许最后一个测试应该改为(or (nil? (type a)) (identical? (type x) js/Object)),因为创建带有空原型的对象的唯一方式是明确地,而且他们这样做是因为它们打算用作关联对象。(http://adripofjavascript.com/blog/drips/creating-objects-without-prototypes.html)

0

评论者:kurtharriger

以上还表明,也许可以扩展nil上的IEncodeClojure?
a 不是 nil,但它的类型是...所以拓展nil上的协议可能应该这样工作?

但是它不行...这可能是在satisfies?中的一个bug?

`
cljs.user=> (def a (.create js/Object nil))

'cljs.user/a

cljs.user=> (aset a "test" 1)
1
cljs.user=> (extend-protocol IEncodeClojure)
nil
(-js->clj (link: x opts))

(let (link: {:keys [keywordize-keys)} opts
      keyfn (if keywordize-keys keyword str)]
  (into {} (for (link: k (js-keys x))
    (link: (keyfn k) (js->clj (unchecked-get x k)) opts))))))

nil
cljs.user=> (js->clj a)

object(link: Object)

cljs.user=> (js-keys IEncodeClojure)

js (link: "null")

cljs.user=> (satisfies? IEncodeClojure a)
false
cljs.user=> (type a)
nil

`

0
_评论者:hpnm_

关于`(identical? (goog/typeOf x) "object")`代替`(identical? (type x) js/Object)`的意见如何?

Closure的typeOf正确返回'null'和'array',并进行了一些针对浏览器特定的修复。
当前的测试看起来代码较少,因此可能需要进行性能测试。

示例
(identical? "object" (goog/typeOf (.create js/Object nil #js {:a #js {:value 1}}))) => true
0
参考:https://clojure.atlassian.net/browse/CLJS-2408 (由 alex+import 报告)
...