2014-06-16 40 views
7

我想實現與ClojureScript的功能,以簡化js/console.log這樣的:JS /的console.log在ClojureScript

(defn log [& args] 
     (apply js/console.log args)) 

調用它:(log "foo" "bar") 拋出:TypeError: Illegal invocation

但這個工程:(js/console.log "foo" "bar")

問題是什麼?

回答

11

js/something用於訪問js對象,但不應該在此之後嵌套點,因爲它不是clojure兼容語法,它將被刪除。在舊版本的編譯器(2138)中,代碼可以工作,但在新版本的編譯器中可能已被棄用。你正在使用哪個版本?

正確的方法是使用簡單的JS互操作是這樣的:[警告:看到大衛·諾倫,ClojureScript首席開發下方評論]

(defn log [& args] (apply (.-log js/console) args)) 

甚至更​​短,因爲執行console.log已經是可變參數(只別名):

(def log (.-log js/console)) 
+7

這是完全正常的寫'JS/console.log'這是支持,永遠不會改變。無論如何,這往往會出現在互操作的情況下,所以無論如何它都是不可移植的。 – dnolen

5

如果您首先將它放在文件頂部(enable-console-print!),也可以使用println。

+1

他們不是完全一樣的東西。 'println'使用clojure的字符串序列化行爲,而大多數瀏覽器中的'console.log'會將對象渲染爲可導航的樹。 – eyelidlessness

3

我發現實際答案

(.apply (.-log js/console) js/console (clj->js args)) 
4

而且pprint已經被移植:

:require [cljs.pprint :refer [pprint]] 
+0

好消息!你是怎麼發現的 ? – nha

+1

來自:http://swannodette.github.io/2015/07/29/clojurescript-17/ 「Shaun LeBron和Jonathan Boston對將Clojure.pprint移植到ClojureScript的工作大加讚賞,以便我們可以看到漂亮打印的AST「。 – bbs

2

這是給你的功能一個工作代碼(與[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) 

這裏是一篇文章,描述爲什麼(應用...)不能很好地使用JS函數。 http://clojurescriptmadeeasy.com/blog/how-to-apply-with-the-console-api.html

1

console.log使用宏而不是函數是有意義的。如果您將log作爲一項功能實施,則所有消息都將使用您定義的log功能的行號進行記錄。

宏解決了編譯過程中產生內嵌代碼這個問題,是要明白,宏在編譯時運行是非常重要的。

macros.cljc定義該宏:

(ns test.macros) 

(defmacro log 
    [& msgs] 
    `(.log js/console [email protected])) 
  • `:就像'quote但:
    • 符號是自動解決,包括其命名空間,防止模棱兩可的符號,在時評價。
    • 可以使用~unquote來插入評估表單,如我爲msgs添加@來解包多個參數:[email protected]。有關更多信息syntax quote

然後從core.cljs稱之爲:

(ns test.core 
    (:require-macros [test.macros :refer [log]])) 

(log "foo" "bar")