我正在调试一些代码,并将我的问题归结为一个简单的例子:
(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/