【问题标题】:Why can't I call seq functions in a sequence generated by js->clj?js->clj生成的序列为什么不能调用seq函数?
【发布时间】:2013-04-09 07:43:03
【问题描述】:

虽然我可以用类似的东西将一个简单的 js 对象变成一个 clojure 对象;

(-> "{a: 2, b: 3}" js* js->clj)

我显然无法在处理函数中使用特定对象 goog.events.BrowserEvent 执行此操作,例如:

(defn handle-click [e]
  ...
  (-> e .-evt js->clj keys) ;; <-------------
  ...

该函数确实被应用了,但生成的对象不响应像countfirst这样的序列函数,尽管我可以使用aget获取项目。我在 chrome 的控制台中收到的错误消息是;

Uncaught Error: No protocol
method ISeqable.-seq defined for type object: [object Object]

为什么会这样? js-&gt;clj 不应该与所有对象一起工作吗?

我该如何解决这个问题?

谢谢!

【问题讨论】:

    标签: clojure clojurescript


    【解决方案1】:

    首先,我在 google 闭包中找到了获取对象的键和值的函数:

     (defn goog-hash-map [object]
       (zipmap (goog.object/getKeys object) (goog.object/getValues object)))
    

    然后,通过研究 cljs.core 的源代码,我意识到我所要做的就是用它扩展 IEncodeClojure 接口:

     (extend-protocol IEncodeClojure
       goog.events.BrowserEvent
       (-js->clj
        ([x {:keys [keywordize-keys] :as options}]
           (let [keyfn (if keywordize-keys keyword str)]
             (zipmap (map keyfn (gobj/getKeys x)) (gobj/getValues x))))
        ([x] (-js->cljs x {:keywordize-keys false}))))
    

    original code 不适用于此对象,因为它的类型必须完全是 Object。我试图将比较函数更改为实例?,即,

    (instance? x js/Object) (into {} (for [k (js-keys x)]
                                          [(keyfn k) (thisfn (aget x k))]))
    

    但这也不起作用,挥舞着以下错误,这让我接受了以前的方法。

    Uncaught TypeError: Expecting a function in instanceof check, 
    but got function Object() { [native code] }`.
    

    【讨论】:

    • (instance? x js/Object) 不起作用,因为instance? 的第一个参数应该是一个类。你应该改用(isa? x js/Object)
    【解决方案2】:

    js-&gt;clj 仅更改完全是 JavaScript 对象的内容(它是使用 instance? 而不是 isa? 实现的,并且有充分的理由),当您传递 js\Object 的后代时,js-&gt;clj 返回同一个对象。 aget(和 aset)之所以有效,是因为它可以编译为 JavaScript 上的 object[field-name] 语法。

    您可以将ISeq 协议(或任何其他协议)扩展到goog.events.BrowserEvent,并且所有适用于ISeq 的功能都适用于goog.events.BrowserEvent。 Chris Houser 有一个talk,他在其中展示了如何将一堆协议扩展到 goog 地图。我建议观看整个演讲,但与您的问题相关的部分从大约 14 分钟开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-17
      • 1970-01-01
      • 2020-10-27
      • 2014-02-13
      • 1970-01-01
      • 2017-12-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多