为什么我不能在 ClojureScript 中访问这个 JS 对象的 props?
Why can I not access this JS object's props in ClojureScript?
我正在调试一些代码,并将我的问题归结为这个简单的例子:
(js/console.log (.-hey (clj->js {:hey "please work!"})))
打印undefined
这肯定与高级优化期间的重命名有关,但我无法弄清楚发生了什么,也不知道如何解决...
如果您使用在线 CLJS REPL,如 http://clojurescript.net/,它会按预期工作(returns 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 文件中保存 space 它用更短的标识符替换名称)。 "hey"
对象中的字符串不会被破坏,因为它是字符串文字,并且会出现不一致。
当您将 clj->js
的结果传递给外部函数(例如在 d3js 中)时,您的代码应该会按预期工作,因为如果您使用带有 externs 文件的缩小版本,则外部库不会被破坏(请参阅@Andre 对你的问题的评论和 CLJS doc about deps and externs.)
当您需要访问示例中的此类属性并需要它与高级优化一起使用时,您可以使用 goog.object/get
or goog.object/getValueByKeys
as described in cljs.core/aget
doc.
我正在调试一些代码,并将我的问题归结为这个简单的例子:
(js/console.log (.-hey (clj->js {:hey "please work!"})))
打印undefined
这肯定与高级优化期间的重命名有关,但我无法弄清楚发生了什么,也不知道如何解决...
如果您使用在线 CLJS REPL,如 http://clojurescript.net/,它会按预期工作(returns 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 文件中保存 space 它用更短的标识符替换名称)。 "hey"
对象中的字符串不会被破坏,因为它是字符串文字,并且会出现不一致。
当您将 clj->js
的结果传递给外部函数(例如在 d3js 中)时,您的代码应该会按预期工作,因为如果您使用带有 externs 文件的缩小版本,则外部库不会被破坏(请参阅@Andre 对你的问题的评论和 CLJS doc about deps and externs.)
当您需要访问示例中的此类属性并需要它与高级优化一起使用时,您可以使用 goog.object/get
or goog.object/getValueByKeys
as described in cljs.core/aget
doc.