2024 Clojure状态调查!中分享你的想法。

欢迎!请查看关于页面以了解更多此工作的信息。

+3
ClojureScript

版本:1.9.946
问题CLJS-1998的后续跟踪

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

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

object[Object]

cljs.user=> (keys (js->clj (.create js/Object nil)))
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

为了了解更多背景信息,具有null原型的对象来源是我在这里使用的第三方库: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)),因为创建具有null原型的对象的唯一方法是显式创建,而且这样做是因为它们打算用作关联对象。(http://adripofjavascript.com/blog/drips/creating-objects-without-prototypes.html

0

评论者为:kurtharriger

上面的内容也暗示了也许可以在nil上扩展IEncodeClojure?
a不是nil,但它的类型是...也许在nil上扩展协议应该会这样工作?

但这没有... maybe this is a bug in satisfies?

`
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
_Comment made by: 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 报告)
...