What are the namespace gotchas for clojurescript when coming from clojure?

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-10 10:34:10

问题


I'm trying to understand the namespacing model in clojurescript. I understand that javascript doesn't come built in with namespace support, so its been an add on via the google closure library. However, I don't understand how clojurescript deals with these differences. Can someone please explain?

Lets say for example I want to use the google charts api and whenever possible would like to use advanced compilation. What do I use in the closure/build call, how would the ns form look like and what's the best way to refer to the api from the code? I've looked at https://github.com/sritchie/contour but that example doesn't use advanced compilation, and I don't see the options referring to the google api in the project.clj file.


回答1:


The namespace declaration is the same regardless of whether you are using simple or advanced mode compilation. The difference is that libraries that don't participate in google dependency management via goog.require('') and goog.provide('') need to be explictly referenced via an externs.js file. This file, which you pass to the cljs compiler, provides stubs of all the vars and associated methods. A typical externs.js would look something like:

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

So to reference a google closure aware library your namespace declaration looks like this:

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

And that emits the following javascript:

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

Note that if you want to call your closurescript from another javascript file then you need to tag the method as exported so that the optimizing compiler knows to preserve the name. (e.g. you might have a script tag on a page from where you want to call a javascript function that has been generated from clojurescript)

That looks like this:

(defn ^:export externallyCalled [])

The other thing to be aware of is that you have to treat macros differently in clojurescript, this is because the ability to process them 'on the fly' in the reader is not present in the same way as it is in clojure.

you do that as follows (note that you are obliged to bind the macros with :as in this case)

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

If you are calling code that didn't participate in google's dependency management you access it via the js namespace and the javascript interop...

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

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

all the usual . variants work too..



来源:https://stackoverflow.com/questions/9723111/what-are-the-namespace-gotchas-for-clojurescript-when-coming-from-clojure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!