我想用ClojureScript实现一个函数,来简化像这样的js/console.log
:
(defn log [& args]
(apply js/console.log args))
调用它:(log "foo" "bar")
会抛出TypeError: Illegal invocation
,但是这个可以正常工作:(js/console.log "foo" "bar")
。
问题出在哪里?
我想用ClojureScript实现一个函数,来简化像这样的js/console.log
:
(defn log [& args]
(apply js/console.log args))
调用它:(log "foo" "bar")
会抛出TypeError: Illegal invocation
,但是这个可以正常工作:(js/console.log "foo" "bar")
。
问题出在哪里?
js/something
用于访问JavaScript对象,但不应在此之后嵌套点号,因为这不是Clojure兼容的语法,并且将被删除。 在编译器的旧版本(2138)中,您的代码可以正常工作,但可能已在编译器的新版本中弃用。 您使用的是哪个版本?
正确的方法是使用直接的js互操作,如下所示: [注意:请参见下面David Nolen,ClojureScript首席开发人员的评论]
(defn log [& args] (apply (.-log js/console) args))
甚至更短,因为console.log已经是可变参数的(只需创建一个别名):
(def log (.-log js/console))
如果你在文件顶部加上 (enable-console-print!)
,那么你也可以只使用 println。
println
使用Clojure的字符串序列化行为,而大多数浏览器中的console.log
将对象呈现为可导航的树形结构。 - eyelidlessness并且pprint已被移植:
:require [cljs.pprint :refer [pprint]]
(.apply (.-log js/console) js/console (clj->js args))
以下是一个已测试通过的函数工作代码(已与[org.clojure/clojurescript "1.7.228"]进行了测试):
; working
(defn log [& args]
(.apply js/console.log js/console (to-array args)))
; not working
; (defn log [& args] (apply (.-log js/console) args))
; (defn log [& args] (apply js/console.log args))
; (def log js/console.log)
console.log
时,与其使用函数,最好使用宏。如果您将log
实现为函数,则所有消息都将在定义log
函数的行号处记录日志。宏在编译时运行
。macros.cljc
中定义此宏:(ns test.macros)
(defmacro log
[& msgs]
`(.log js/console ~@msgs))
'
或quote
,但是:
~
或unquote
插入评估的表单,就像我为msgs
添加@
以解包多个参数一样:~@msgs
。有关语法引用的更多信息。然后从core.cljs
调用它:
(ns test.core
(:require-macros [test.macros :refer [log]]))
(log "foo" "bar")
js/console.log
是完全可以的,这是被支持的,也不会改变。这通常发生在互操作情况下,因此它本来就不可移植。 - dnolen