Skip to content
Matt Huebert edited this page Feb 28, 2019 · 4 revisions

On Performance

I have tried to tune the macros so that they emit code (via :advanced compilation) that's similar to what you might write by hand in javascript, so that you can use this even for relatively performance-sensitive code.

For very performance-sensitive contexts, you can forego null-safety by using "unchecked" operations, which will throw errors if passed nil. Two are available in js-interop: j/unchecked-get and j/unchecked-set, used as follows:

(j/unchecked-get o :someKey) ;; returns `o`
(j/unchecked-get o .-someKey) ;; works with renamable keys

(j/unchecked-set o :a 10 :b 20) ;; can set multiple properties at once
(j/unchecked-set o .-a 10 .-b 20)

These are not recommended unless you really need them.

On renamable vs. static keys

The general rule is that you should use "renamable" keys (ie. use dot-syntax, like .-someKey) for code that is run through the Closure compiler, which usually means ClojureScript code.

Objects created using js literal syntax, like #js:{:hello "world}, do not have renamable keys, so you should use string/keyword keys to access them. Similarly, objects created from parsing JSON, for example data that you fetch from an API, are also not renamable.

(-> (fetch-post ...)
    (.then (fn [post] (j/get post :title))))

Extending the global object

It's possible to implement ILookup for "all" JavaScript objects, as explained by Mike Fikes here. This will only have an effect on plain objects whose prototype is js/Object, not for any other kind of object (eg. it won't work for browser events or React components). It also mutates the global js/Object.

How it's done:

Associative destructuring is based on get, which can be mapped onto goog.object/get for JavaScript objects by extending them to ILookup:

(extend-type object
 ILookup
 (-lookup 
  ([o k] 
    (goog.object/get o (name k)))
  ([o k not-found] 
    (goog.object/get o (name k) not-found))))
Clone this wiki locally