CoffeeScript with other libraries
I recently started reading about CoffeeScript http://jashkenas.github.com/coffee-script/ and it looks absolutely amazing! However I can't seem to figure out if there's an easy way to access/use external JavaScript apis. I use OpenLayers extensively so could someone show me how the following snippet would be written in CoffeeScript?
var map = new OpenLayers.Map('map_div', {
controls: [
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.LayerS开发者_如何转开发witcher({'ascending':false})
],
numZoomLevels: 6
});
One slight gotcha to be aware of is that the object system in OpenLayers uses a function called initialize() as the constructor, so in order to have CoffeeScript's super keyword work correctly when you extend OpenLayers classes, you'll need to decorate them. I use the following function for this:
window.CompatibleClass = (cls) ->
class Wrapped
constructor: ->
# Call the OpenLayers-style constructor.
cls::initialize.apply @, arguments
# Copy prototype elements from OpenLayers class.
Wrapped::[name] = el for name, el of cls::
Wrapped
Now you can extend an OL built-in like so:
class MySpecialFeature extends (CompatibleClass OpenLayers.Feature.Vector)
constructor: ->
super new OpenLayers.Geometry.Point 0, 0
CLASS_NAME: "MySpecialFeature"
EDIT: Just to clarify, the two alternatives to wrapping the class like this are to use the OpenLayers class system as-is, and miss out on some of the syntax benefits of CoffeeScript, or to manually call the initialize function in each constructor, which feels more brittle, and spreads around the dependency, rather than concentrating it in a single decorator.
Using the OpenLayers class system as-is, in CoffeeScript:
MySpecialFeature = OpenLayers.Class OpenLayers.Feature.Vector,
initialize: ->
# Call super using apply, as is convention in OpenLayers
OpenLayers.Feature::initialize.apply @, new OpenLayers.Geometry.Point 0, 0
...
...
Alternatively, using CoffeeScript classes, but extending an OpenLayers class un-decorated:
class MySpecialFeature extends OpenLayers.Feature.Vector
constructor: ->
# Call inherited initialize().
@initialize.apply @, new OpenLayers.Geometry.Point 0, 0
...
...
Neither of these methods will be as idiomatic or recognizable to other developers, either of OpenLayers or CoffeeScript. I stand by my recommendation of a wrapper which allows native super() use in calling OpenLayers constructors.
You have a bit of flexibility in how much syntax you use, but this is how I'd write it:
map = new OpenLayers.Map 'map_div',
controls: [
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.LayerSwitcher ascending: false
]
numZoomLevels: 6
This compiles into
var map;
map = new OpenLayers.Map('map_div', {
controls: [
new OpenLayers.Control.PanZoomBar(), new OpenLayers.Control.LayerSwitcher({
ascending: false
})
],
numZoomLevels: 6
});
which is essentially the same as your JavaScript code.
精彩评论