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

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

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

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

嗯,知道我在哪里搞砸了吗?

编辑:
经过进一步思考,以及 clojurians 对 slack 的一些建议,我认为这是因为优化会破坏关键字,当我使用 clj->js 时。

我发现我(认为)我需要这样做,因为我试图与 D3.js 库(来自 cljsjs)互操作,当我传递它时,它期待 js 对象,而不是 cljs 对象。是否有一种惯用的方式将 cljs 对象传递给您正在与之互操作的 js 库? (如果这确实是我的问题?)

最佳答案

使用高级优化编译时,您的代码将不起作用。您可以检查它比较使用不同优化设置编译的版本。

产生 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 对您的问题和 CLJS doc about deps and externs 的评论。 )

当您需要访问示例中的此类属性并需要它与高级优化一起使用时,您可以使用 goog.object/get goog.object/getValueByKeys ,如 cljs.core/aget doc 中所述。

关于clojure - 为什么我不能在 ClojureScript 中访问这个 JS 对象的 Prop ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35527115/

10-13 03:45