ClojureScript交互操作

14

我试图找出如何在ClojureScript中访问JavaScript对象属性。如果我预先知道属性的名称,那很容易。要获取foo.bar,我只需要执行

(.-bar foo)
有没有一种方式可以在运行时仅知道属性名称的情况下访问该属性?我正在寻找JS语法foo[dynamicBar]的等效方法。
2个回答

19

你可以使用aget / aset来访问仅在运行时才知道的属性。

;; Use clj->js to convert clj(s) map to javascript.
;; Note the #js {:bar 100} reader literal indicating a js map.

cljs.user> (def foo (clj->js {:bar 100}))
#js {:bar 100}
cljs.user> (.-bar foo) 
100
cljs.user> (aget foo "bar")
100
cljs.user> (aset foo "baz" 200)
200
cljs.user> (.-baz foo) 
200

1
有人可能想知道,今天至少可以使用(js-obj "bar" 100),避免使用js*的需要。 - Leon Grapenthin

1

当您想要利用 :optimizations :advanced 编译器模式,但没有外部文件覆盖您的代码时,使用字符串名称也可能很重要。

请参见 David Nolen 使用 goog.object.get 的示例: https://github.com/clojure/clojurescript/wiki/Dependencies#using-string-names

虽然 aget 也可以工作。但是此方法最初旨在为您提供对数组元素的访问,而不是一般 js 对象的属性。goog.object 的 get 方法是传达您意图的更好方法。

以下是这两种方法的实现方式: https://github.com/google/closure-library/blob/1b8a893271d790626b5cd652b922675c987f106d/closure/goog/object/object.js#L403

https://github.com/clojure/clojurescript/blob/d2d031605b1ad552077218c8f445868653c01744/src/main/clojure/cljs/core.cljc#L942

正如您所看到的, (aget o key) 直接生成 JavaScript 代码 o[key],但 goog.object.get 调用一个方法,该方法首先检查 o 中是否存在该键。

在ClojureScript中,我认为直接使用goog.object.get是一种反模式。这会导致代码变得更加丑陋。如果需要进行检查,则可以轻松地在其中添加,而不需要使用它。如果通常需要进行检查,则可以认为aget应该执行此操作或具有可选参数以执行此操作。或者,您可以自己编写代码。任何事情都比在各个地方放置丑陋的闭包全名要好得多。 - user1969453

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接