我正在调试一些代码,并将我的问题归结为一个简单的例子:
(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库的惯用方法? (如果这确实是我的问题?)
答案 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/getValueByKeys
或cljs.core/aget
doc。