为什么我不能在ClojureScript中访问这个JS对象的道具?

时间:2016-02-20 18:13:36

标签: clojure clojurescript

我正在调试一些代码,并将我的问题归结为一个简单的例子:

(js/console.log (.-hey (clj->js {:hey "please work!"})))

打印undefined

它必须与高级优化期间的重命名有关,但我无法弄清楚发生了什么,也无法解决它...

如果您使用在线CLJS REPL,例如http://clojurescript.net/,它会按预期工作(返回nil但会打印please work!),但在使用cljsbuild的高级优化下,根本不起作用!

嗯,有什么想法,我搞砸了吗?

修改 经过进一步反思,以及来自clojurians的一些关于松弛的建议,这是因为当我使用clj->js时,优化会破坏关键字。

我发现我(想)我需要这样做,因为我正在尝试与D3.js库(来自cljsjs)互操作,当我传递它的东西时,它期待js个对象,不是cljs个对象。是否存在将cljs对象传递给您正在使用的js库的惯用方法? (如果这确实是我的问题?)

1 个答案:

答案 0 :(得分:3)

使用高级优化编译时,您的代码将无法运行。您可以检查它与使用不同优化设置编译的版本进行比较。

生成JS对象的部分正常工作,例如以下工作:

(.log js/console (clj->js {:hey "please work"}))

将产生

Object {hey: "please work"}

但是在使用高级优化进行编译期间,访问hey属性的部分将会中断。

编译时

(.log js/console (.-hey (clj->js {:hey "please work"})))

你会得到类似的东西:

使用optimizations :none

console.log(
  cljs.core.clj__GT_js.call(
    null,new cljs.core.PersistentArrayMap(null, 1,
      [new cljs.core.Keyword(null,"hey","hey",301812684),"please work"], null)
  ).hey);

使用optimizations :advanced

console.log(Tg(new jb(null,1,[Nh,"please work"],null)).ci);

注意.hey属性键是如何被绑定到.ci的。这是因为Google Closure在优化阶段重命名了它(为了节省结果JS文件中的空间,它用更短的标识符替换名称)。对象中的"hey"字符串不会被破坏,因为它是一个字符串文字而且你得到了不一致。

当您将clj->js的结果传递给外部函数(例如在d3js中)时,您的代码应该按预期工作,因为如果您使用具有externs文件的缩小版本,外部库将不会被破坏(请参阅@ Andre's对您的问题发表评论并CLJS doc about deps and externs。)

当您需要访问示例中的此类属性并需要使用高级优化时,您可以使用goog.object/get中描述的goog.object/getValueByKeyscljs.core/aget doc