Clojurescript:扩展 Javascript class

Clojurscript: extend a Javascript class

我正在尝试使用特定的 JavaScript 框架,该框架需要扩展基础 class 才能将其用于应用程序。

基本上我想按照惯用的 ClojureScript 执行以下操作。

class Foo extends Bar {
  constructor() { super("data") }
  method1(args) { /* do stuff */ }
}

我试过了

(defn foo
  []
  (reify
    js/Bar
    (constructor [this] (super this "data"))
    (method1 [this args] )))

如果我从 Object 创建一个新的 class,这会起作用,但是正如 shadow-cljs 正确地抱怨的那样,"Symbol js/Bar is not a protocol"。另外,我不想添加方法,而是创建一个继承某些方法并重载其他方法的子class。

我考虑过使用 proxy,但 "core/proxy is not defined"。

当然我可以创建 Bar 的实例和 set! 新方法,但这感觉就像放弃并使用劣质语言。

CLJS 没有内置支持 class ... extends ...

您可以自己将它与一些样板一起破解,您可以通过宏生成样板以使其看起来更漂亮。

(ns your.app
  (:require
    [goog.object :as gobj]
    ["something" :refer (Bar)]))

(defn Foo
  {:jsdoc ["@constructor"]}
  []
  (this-as this
    (.call Bar this "data")
    ;; other constructor work
    this))

(gobj/extend
  (.-prototype Foo)
  (.-prototype Bar)
  ;; defining x.foo(arg) method
  #js {:foo (fn [arg]
              (this-as this
                ;; this is Foo instance
                ))})

CLJS(仍然)没有 built-in 支持 class ... extends ...

但是在最近的 shadow-cljs 版本中,我添加了对 classextends 的支持。这将发出一个标准的 JS class 并且不需要任何 hacky 变通办法来让它工作。

翻译这个例子

class Foo extends Bar {
  constructor() { super("data") }
  method1(args) { /* do stuff */ }
}

会是

(ns your.app
  (:require [shadow.cljs.modern :refer (defclass)]))

(defclass Foo
  ;; extends takes a symbol argument, referencing the super class
  ;; could be a local symbol such as Bar
  ;; a namespaced symbol such as alias/Bar
  ;; or just a global via js/Bar
  (extends Bar)

  (constructor [this]
    (super "data"))

  ;; adds regular method, protocols similar to deftype/defrecord also supported
  Object
  (method1 [this args]
    ;; do stuff
    ))

可以找到 defclass 的更复杂示例 here and here

目前这仅与 shadow-cljs 一起提供,但从技术上讲,您可以从 here 获取 modern.cljcmodern.cljs 文件并将它们放入您的项目中。它应该适用于所有构建工具。