Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
87 lines (66 sloc) 1.77 KB


Sometimes you write JavaScript like this:

var Bag = function() { = [];

Bag.prototype.add = function(val) {;

Bag.prototype.print = function(val) {

var mybag = new Bag();

Sometimes you have to do it in ClojureScript, like when talking to some JS libraries. Or your love for objects is so strong that you venture off the True Path and just want to do it.

Normally ClojureScript would make it look like this:

(defn Bag []
  (this-as this
           (set! (.-store this) (array))

(set! (.. Bag -prototype -add)
      (fn [val]
        (this-as this
                 (.push (.-store this) val))))

(set! (.. Bag -prototype -print)
      (fn []
        (this-as this
                 (.log js/console (.-store this)))))

(def mybag (Bag.))
(.add mybag 5)
(.add mybag 7)
(.print mybag)


Take this little painkiller pill here and it will look more like:

(defn Bag []
  (this-as this
           (set! (.-store this) (array))

(set-obj-fn Bag.prototype.add [val]
            (.push (.-store this) val))

(set-obj-fn Bag.prototype.print [val]
            (.log js/console (.-store this)))

There are two macros in the package. set-obj-fn shown above, which binds the function to path on object that looks more like JS.

There also is obj-fn, which only eliminates the need for explicit this-as:

(set! (.. Bag -prototype -add)
      (obj-fn [val]
        (.push (.-store this) val)))

All you need is:

; project.clj
[cljs-painkiller "0.1.0"]
; my-namespace.cljs:
(:use-macros [painkiller.macros :only [obj-fn set-obj-fn]])
Something went wrong with that request. Please try again.