. dot

special charactersince v0.0-927 in clojureEdit

Dots can be used inside symbols for JS interop.

  • (.foo bar) => bar.foo()
  • (.-foo bar) => bar.foo
  • (foo.) => new foo()

Details:

A dot's meaning depends on its position in the symbol:

  • . (by itself), .-foo, .foo all refer to the interop . (special form).
  • foo. is constructor sugar, meaning (new foo).
  • (ns foo.bar) and foo.bar/baz means that foo.bar is a nested namespace.
  • foo/bar.baz or bar.baz means bar.baz is nested JS property access (not allowed in clojure).

Dots inside symbols accidentally work as a technical shortcut in ClojureScript, but this is not valid in Clojure.

  • foo.bar.baz => foo.bar.baz (not recommended)
  • (foo.bar.baz) => foo.bar.baz() (not recommended)

Dots inside symbols are not recommended, as they are not detected by :infer-externs. For example, no externs are generated for (foo.bar) if ^js foo is annotated.


Examples:

For interop:

(def obj #js {:age 28, :greet #(str "Hi " %)})

(. obj greet "Bob")
;;=> "Hi Bob"

(.greet obj "Bob")
;;=> "Hi Bob"

(. obj -age)
;;=> 28

(.-age obj)
;;=> 28

For constructor:

(deftype Foo [x]
   Object
   (toString [_] (str "Foo:" x)))

(Foo. 1)
;;=> #

(new Foo 1)
;;=> #

For nested namespaces:

(ns example.nested.core)
(def foo 1)
example.nested.core/foo
;;=> 1

For nested JS properties. The following pairs are equivalent:

(js/console.log "HELLO")
;; "HELLO"

(.log js/console "HELLO")
;; "HELLO"
cljs.core/PersistentQueue.EMPTY
;;=> #queue []

(.-EMPTY cljs.core/PersistentQueue)
;;=> #queue []

See Also: