1

我正在使用 ClojureScript 来检测定义了哪个浏览器特定版本的“requestAnimationFrame”方法。我使用以下代码:

(defn animationFrameMethod []
  (let [window (dom/getWindow)
        options (list #(.-requestAnimationFrame window)
                      #(.-webkitRequestAnimationFrame window)
                      #(.-mozRequestAnimationFrame window)
                      #(.-oRequestAnimationFrame window)
                      #(.-msRequestAnimationFrame window))]
    ((fn [[current & remaining]]
       (cond
        (nil? current) #((.-setTimeout window) % (/ 1000 30))
        (fn? (current)) (current)
        :else (recur remaining)))
     options)))

这很好用,而且并不可怕,但我真的希望能够将方法名称放在一个列表中,即

'(requestAnimationFrame webkitRequestAnimationFrame ...)

然后为列表中的每个符号调用一个宏来生成匿名函数代码。

我想要这样的工作:

user> (def name webkitRequestAnimationFrame)
user> (macroexpand '(macros/anim-method name window))
#(.-webkitRequestAnimationFrame window)

但是我玩了一段时间的宏,并没有达到这个效果。部分问题是方法名称和点符号的工作方式很奇怪,我什至不确定这是否可能。

有什么技巧可以让它工作吗?谢谢!

4

1 回答 1

2

请记住,javascript 对象也是关联哈希,所以这样的事情应该可以在不求助于宏(未经测试)的情况下工作......

(def method-names ["requestAnimationFrame"
                   "webkitRequestAnimationFrame"
                   "mozRequestAnimationFrame"
                   "oRequestAnimationFrame" 
                   "msRequestAnimationFrame"])

(defn animationFrameMethod []
  (let [window (dom/getWindow)
        options (map (fn [n] #(aget window n)) method-names)]
    ((fn [[current & remaining]]
       (cond
        (nil? current) #((.-setTimeout window) % (/ 1000 30))
        (fn? (current)) (current)
        :else (recur remaining)))
     options)))
于 2012-03-27T17:45:01.720 回答