我想編寫一個程序,爲div添加複雜行爲(例如,考慮某種交互式圖形)。我想能夠將一個div傳遞給庫中的一個函數,並讓該庫爲div添加行爲。什麼是ClojureScript等效於採用參數的JavaScript作用域
如果我在JavaScript中這樣做,我會寫下面的內容。
在my_page.html
:
<div id="program-container"></div>
<script src="my_library.js" type="text/javascript"></script>
<script type="text/javascript">
useDivForACoolProgram(document.getElementById("program-container"));
</script>
在my_library.js
:
function useDivForACoolProgram(div) {
var x = 2;
var y = 3;
function setup() {
div.innerHTML = "Getting ready to run...";
doMainSetup();
}
function doMainSetup() {
...
// Lots more functions, many of which refer to div
}
注意,庫公開它接受一個div單個功能。當我們將一個div傳遞給它時,庫將它的所有狀態保存在一個與通過的div相關的閉包中,如果我這麼傾向的話,這可能會讓我將這種行爲添加到頁面上的許多div上。
我想在ClojureScript中做同樣的事情。我第一次嘗試如下:
(defn use-div-for-a-cool-program [div]
(def x 2)
(def y 3)
(defn setup []
(set! (.innerHTML div) "Getting ready to run...")
(do-main-setup))
(defn do-main-setup []
...
;; Lots more functions, many of which refer to div
)
但是,這並不工作,因爲def
和defn
定義在模塊的範圍內的變量,而不是定義局部變量use-div-for-a-cool-program
。如果我用不同的divs多次呼叫use-div-for-a-cool-program
,則所有新的def
s和defn
s都會覆蓋舊的每次。
一種解決方案是使用let
來代替,但是這有點令人不滿意,因爲它迫使我們在函數被引用之前給予實現並且也難以閱讀,例如,
(defn use-div-for-a-cool-program [div]
(let [x 2
y 3
do-main-setup (fn []
...)
setup (fn []
(set! (.innerHTML div) "Getting ready to run...")
(do-main-setup))
;; Lots more functions, many of which refer to div
]
(setup)))
有沒有更好的解決方案?
我喜歡你在這裏想要做的,但是假設我的程序帶有狀態。作爲一個簡單的例子,假設我想跟蹤div被點擊了多少次。如果我用閉包來做這件事,我會在閉包中保留一個可變變量,這樣我的所有函數都可以引用它,並且每個div都會自動獲取它自己的變量。你的榜樣在哪裏保持這種狀態? – dphilipson 2015-01-21 19:07:23