一個cljs文件定義一個命名空間,經過命名空間能夠有效組織代碼,這是構建大型系統必備的基礎設施。本篇咱們就深刻理解cljs中的命名空間吧!html
每一個cljs文件首行非註釋的內容一定以下git
(ns my-project.core)
而當前的cljs文件路徑爲${project_dir}/src/my_project/core.cljs
,很明顯命名空間與源碼文件路徑是一一對應的,對應規則是-
對應_
,.
對應/
咯~github
要使用其餘命名空間下的成員,那麼必須先將其引入到當前命名空間才能夠。但注意的是,默認狀況下會自動引入cljs.core
這個命名空間,並且會將其成員注入到當前命名空間中。所以(ns my-project.core)
最後會編譯爲等價於如下語句app
;; 注意:cljs中並不支持:all這種引入,所以這面語句僅僅用於表達注入全部成員而已 (ns my-project.core (:require [cljs.core :all]))
因此咱們能夠直接調用reduce
而不是cljs.core/reduce
。
咱們沒可能只調用cljs.core
的成員吧,那到底如何引入其餘命名空間呢?下面咱們一一道來!ide
:require
1.直接引入函數
(ns my-project.core (:require clojure.data)) ;; 使用時須要指定成員所屬的命名空間 (clojure.data/diff 1 2)
2.注入成員到當前命名空間優化
; 將clojure.data/diff和clojure.data/Diff兩個成員注入到當前命名空間 (ns my-project.core (:require [clojure.data :refer [diff Diff]])) ;; 直接使用便可 (diff 1 2) (defrecord MyRecord [x] Diff (diff-similar [a b] (= (:x a) (:x b))))
3.爲命名空間起別名ui
(ns my-project.core (:require [clojure.data :as data])) ;; 使用時須要指定成員所屬的命名空間的別名 (data/diff 1 2)
4.重命名注入的成員code
(ns my-project.core (:require [clojure.data :refer [diff] :rename {diff difference}])) ;; 使用時僅能使用別名 (difference 1 2) ;; (diff 1 2) 這裏使用原名會報錯
5.引入同命名空間的marcoorm
;; 引入helper.core下的全部macro (ns my-project.core (:require [helper.core :as h :include-macros true])) (h/i-am-macro1) (h/i-am-macro2) (h/i-am-function) ;; 引入helper.core下指定的macro (ns my-project.core (:require [helper.core :as h :refer-macros [i-am-macro1]])) (h/i-am-macro1) ;; 能夠不用指定marco所屬的命名空間哦! (i-am-macro1) (h/i-am-function)
helper/core.cljs文件
(ns helper.core) (defn i-am-function [] (println "i-am-function"))
helper/core.clj文件
(ns helper.core) (defmacro i-am-macro1 [] '(println "i-am-macro1")) (defmacro i-am-macro2 [] '(println "i-am-macro2"))
因爲macro是在編譯期展開爲列表,而後在運行時解析列表,而JS做爲腳本語言根本就沒有全部編譯期,所以須要將macro寫在獨立的clj文件中,而後在cljs編譯爲js時展開。因此當咱們在同一個命名空間定義普通成員和macro時,只需命名兩個名稱同樣當擴展名不一樣的cljs和clj便可。
6.一次引入多個命名空間
(ns my-project.core (:require [clojure.data :as data] [cljs.test :refer [is]] clojure.string))
:use
:use
其實至關於:require
加上:refer
那樣,通常建議用後者代替。
(ns my-project.core (:use clojure.data :only [diff Diff])) (diff 1 2)
(ns my-project.core (:use clojure.data :only [diff] :rename {diff difference})) (difference 1 2)
:require-macros
引入macro其實經過:require
中引入macro已經間接接觸到:require-macros
了,由於它實際上會解析成:require-macros
來使用的!
1.爲命名空間起別名
(ns my-project.core (:require-macros helper.core :as h)) (h/i-am-macro1)
2.注入macro到當前命名空間
(ns my-project.core (:require-macros helper.core :refer [i-am-macro1])) (i-am-macro1)
3.注入macro到當前命名空間,並起別名
(ns my-project.core (:require-macros helper.core :refer [i-am-macro1] :rename {i-am-macro1 m1})) (m1)
:use-macros
引入macro :use-macros
其實至關於:require-macros
加上:refer
那樣,通常建議用後者代替。
(ns my-project.core (:use-macros helper.core :only [i-am-macro1])) (i-am-macro1)
(ns my-project.core (:use-macros helper.core :only [i-am-macro1] :rename {i-am-macro1 m1})) (m1)
:import
引入Google Closure中的類型和枚舉類 注意:import
只能用於引入Google Closure中的類型,而其餘類型、成員等等所有用:require
引入就行了。
(ns my-project.core (:import goog.math.Long [goog.math Vec2 Vec3])) (Long. 4 6) (Vec2. 1 2) (Vec3. 1 2 3)
:refer-clojure
重置clojure內置的symbol 咱們知道默認狀況下會自動注入cljs.core
的成員到當前命名空間中,所以咱們能夠直接使用+
、-
等函數。若是此時咱們自定義一個名爲+
的函數,那麼就會讓下次要使用加法函數時則須要寫成cljs.core/+
,這樣總感受不太好。那麼咱們能夠藉助:refer-clojure
來重置這些內置symbol了。
(ns my-project.core (:refer-clojure :rename {+ math_add})) (defn + [& more] (apply math_add more))
另外還能夠直接丟棄(不用就不要注入夠環保的啊!)
(ns my-project.core (:refer-clojure :exclude [+])) (+) ;; 報錯了!
clojure.*
將自動轉爲cljs.*
cljs的好處就是能夠直接使用與宿主環境無關的clj代碼,因此咱們能夠直接引入clojure.string
、clojure.data
等命名空間,但有時難免會記錯或新版本提供了更貼地氣(針對特定宿主優化過)的版本,那是否是就要改爲cljs的版本呢?放心cljs編譯器會自動幫你搞定!
(ns testme.core (:require [clojure.test])) ;; 會自動轉換爲 (ns testme.core (:require [cljs.test :as clojure.test]))
require
用在REPL中就行了 在REPL中咱們會使用如require
、use
、require-macros
、import
等macro來引入命名空間。請緊記,這些確實僅僅用於REPL中而已。並且當咱們修改源碼後,須要經過(require 命名空間 :reload)
來重置並從新加載這個命名空間,不帶:reload
的話新修改的功能將不會生效哦!
注意:require
後的命名空間須要以單引號爲起始,從而避免將其從symbol解析爲var而後取其值。如
(require 'clojure.data) (require '[clojure.set :as s])
根據clojure-style-guide描述優先級別以下::require :as
> :require :refer
:require
> :use
而聲明順序以下::refer-clojure
>:require
>:import
如今咱們能夠安心開始書寫第一個自定義命名空間了,可是不是仍是有點不安穩的感受呢?是否是上面提到Special Form
、Symbol
、Var
等一頭霧水呢?下一篇(cljs/run-at (JSVM. :browser) "簡單類型可不簡單啊~")
尊重原創,轉載請註明來自:http://www.cnblogs.com/fsjohn... ^_^肥仔John