Error formatting macro: pagetree: java.lang.NullPointerException
Skip to end of metadata
Go to start of metadata
You are viewing an old version of this page. View the current version. Compare with Current  |   View Page History

Problem 1: ClojureScript functions as object methods

In any programming language with both first class functions and objects, the handling of a this parameter is a cause for complication. In the case of JavaScript the picture is particularly sticky due to langauge foibles. An additional complication, ClojureScript does not have its own notion of this independent to its JavaScript interop. Currently, there is no good way to refer to a JavaScript this aside from the (js* "this") hack. ClojureScript should more effectively handle this in a way that is safe and intuitive.

A bit about this in general

ClojureScript functions are compiled to JavaScript functions and are therefore subject to the implicit this behavior.

Given a function f defined as:

    function f(a,b) {

Calling f directly yields:

    // [object global],1,2

note: in JavaScript strict mode this would be bound to undefined in the previous example

In this case, the this variable is implicitly bound to the global object.

However, when bound as a property on an object, f's implicit this changes:

    var o = {}
    o.m = f
    // [object Object],1,2

Now the value of this is the instance o.

ClojureScript and this

The problem in ClojureScript can be illustrated in the following:

    (defn f [a b] (println [(js* "this") a b])) ;;roughly equivalent to the f function above

    (def o (js* "{}"))
    (set! cljs.user.o.m f)
    ((.m o) 1 2)
    ;; [#<[object Global]> 1 2]

That is, the value for this in the body of f is bound to the global object and not the instance o.

A possible solution for ClojureScript functions as methods

One possible solution to this dilemma is to use GClosure's bind function:

    (set! cljs.user.o.m (goog.bind f o))
    ((.m o) 1 2)
    ;; [#<[object Object]> 1 2]

This will also work for multi-arity functions.

A possible syntax

    (extend-object o
      {:m f})

Would expand into a number of calls to goog.bind on the object o and then return o itself. The use of the (js* "this") could possibly be replaced with the js namespaced reference js/this.

Problem 2: ClojureScript functions and co-opted this

Some JavaScript libraries use this as a dynamic variable bound to some special value within special contexts. For example, JQuery uses this approach:


Unknown macro: { alert(index + '}


In this example, this would be bound to each element in turn retrieved by the selector $('li') and processed in the each loop. techniques of this sort pull this off by explicitly passing a value for the implicit this to the target function as an argument to the call method. In other words, something (in spirit) like:

(defn f [] js/this)
;=> #<[object Global]>

(.call f (js* "{}"))
;=> #<[object Object]>

This is effectively what goog.bind does, so this type of behavior should just work using ClojureScript functions.