2012-03-15 70 views
12

我想了解clojurescript中的命名空间模型。据我所知,JavaScript并没有内置命名空间支持,所以它是通过google封闭库添加的。但是,我不明白clojurescript如何处理这些差异。有人可以解释吗?clojurescript来自clojure的命名空间陷阱是什么?

比方说,我想使用谷歌图表api,并尽可能使用先进的编译。我在closure/build调用中使用什么,ns表单将如何以及从代码中引用api的最佳方式是什么?我已经看过https://github.com/sritchie/contour,但该示例不使用高级编译,并且我没有在project.clj文件中看到引用google api的选项。

回答

12

无论您是使用简单还是高级模式编译,名称空间声明都是相同的。不同之处在于,不通过goog.require('')goog.provide('')参与谷歌依赖管理的库需要通过externs.js文件明确引用。这个文件,你传递给cljs编译器,提供所有变量和相关方法的存根。一个典型的externs.js看起来是这样的:

// contents of externs.js 
var externalLibrary = {} 
var externalLibrary.method = function() {} 

所以引用了谷歌关闭意识到库中的命名空间声明如下:

(ns my.namespace 
    (:require [goog.events.KeyCodes :as key-codes]) 

并发出以下JavaScript:

goog.provide("my.namespace"); 
goog.require("goog.events.keycodes"); 

请注意,如果您想从另一个JavaScript文件调用closurescript,则需要将方法标记为导出,以便优化编译器知道s保存名字。 (例如,你可能会从要调用已从clojurescript生成的JavaScript函数的网页上的脚本标签)

,看起来像这样:

(defn ^:export externallyCalled []) 

另外要注意的就是你必须在clojurescript中以不同的方式对待宏,这是因为在读者中“动态”处理它们的能力并不像clojure中那样。

你做到这一点,如下所示(请注意,您有义务宏与绑定:在这种情况下)

(ns my.namespace 
    (:require-macros [my.macros :as my])) 

如果你拨打的是没有参加谷歌的依赖管理代码,那么你访问它通过js命名空间和javascript interop ...

(. js/nonGoogle (method args)) ; a method access 

(. js/nonGoogle -p) ; a property access 

所有通常情况。变种工作太..

+0

是:作为选项支持:使用?在requre-macros例子中,应该也有一个向量?另外,你可以举一个谷歌地图或图表api的例子吗? – bmillare 2012-03-19 12:28:11

+0

@bmillare都很好的捕获。我确定了答案。谢谢(很多延迟) – sw1nn 2013-07-24 13:12:59