javascript - 将 JavaScript 对象转换为 ClojureScript : Getter and Setter Properites

标签 javascript clojure clojurescript

我正在努力解决以下问题:

通常 JS 对象通过 js->clj 转换为 ClojureScript。 这适用于原型(prototype)对象的对象。 对于我正在使用的其他人:

(defn jsx->clj [o]
  (reduce (fn [m v] (assoc m (keyword v) (aget o v)))  {} (.keys js/Object o)))

我发现,“属性”,即幕后的 getter 函数,不能通过这些操作进行转换。

有人有这方面的经验吗?

最佳答案

当你说“幕后的 getter 函数不能被这些操作转换”时,我不确定你的意思。

问题之一是,当您将 JS 对象转换为 CLJS 映射时,getter 和 setter 将不会绑定(bind)到原始 JS 对象,因此它们将无法访问该对象的属性。

考虑以下代码:

;; This is your function, no changes here.
(defn jsx->clj [o]
  (reduce (fn [m v] (assoc m (keyword v) (aget o v)))  {} (.keys js/Object o)))


;; This is an improved version that would handle JS functions that
;; are properties of 'o' in a specific way - by binding them to the
;; 'o' before assoc'ing to the result map.
(defn jsx->clj2 [o]
  (reduce (fn [m v]
            (let [val (aget o v)]
              (if (= "function" (goog/typeOf val))
                (assoc m (keyword v) (.bind val o))
                (assoc m (keyword v) val))))
          {} (.keys js/Object o)))

;; We create two JS objects, identical but distinct. Then we convert
;; both to CLJS, once using your function, and once using the improved
;; one.
;; Then we print results of accessing getter using different methods.
(let [construct-js (fn [] (js* "new (function() { var privProp = 5; this.pubProp = 9; this.getter = function(x) { return privProp + this.pubProp + x; }; })"))
      js-1 (construct-js)
      js-2 (construct-js)
      clj-1 (jsx->clj js-1)
      clj-2 (jsx->clj2 js-2)]
  (.log js/console "CLJS objects: " (.getter js-1 10) ((:getter clj-1) 10) (.getter js-2 10) ((:getter clj-2) 10)))

打印:

CLJS objects:  24 NaN 24 24

这意味着以下代码:((:getter clj-1) 10) 失败,而 ((:getter clj-2) 10) 按预期工作。第二个有效,因为 .bind()已用于将函数与 JS 对象正确绑定(bind)。

这个问题,如果这确实是你失败的原因,那么它相当于 JS 中有时会犯的以下错误:

var Constructor = function() {
  var privProp = 5;
  this.pubProp = 9;
  this.getter = function(x) {
    return privProp + this.pubProp + x;
  };
}
var obj1 = new Constructor();
var obj2 = new Constructor();
var fn1 = obj1.getter;             // Invalid, fn1 will not be bound to obj1.
var fn2 = obj2.getter.bind(obj2);  // Note .bind here.
console.log(fn1(10), fn2(10));

打印类似的输出:

NaN 24

同样,尚未绑定(bind)到 obj1fn1 返回了无效输出。

关于javascript - 将 JavaScript 对象转换为 ClojureScript : Getter and Setter Properites,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35105557/

相关文章:

javascript - 动态搜索栏建议

javascript - 配置 - 是否有基于 Web 的 github 连接工具?

javascript - Express 端点对于 POST 返回 404,对于 GET 返回 200

c++ - 您将如何在 Clojure 中编写此 C++ 循环?

protocols - 在 ClojureScript 中扩展协议(protocol)以从 native js 对象中获取值

javascript - 尝试映射 Enum 键以生成 JSX 元素时出现 Typescript 错误

clojure - 翻译字符串的编码

clojure - 在 clojure 中,如果定义为 [x] 参数然后引用为 x,为什么不识别 x?在代码块中?

clojure - 将抽象/空变量传递给函数 Clojure

clojure - 用 clojure 编写的桌面应用程序