问题
I have a habit of making questions unnecessarily long by including off-topic and useless rants. I'll try not to do it this time. I apologize for the lack of a better and more descriptive title.
So, here's a CoffeeScript code.
(($, window, document) ->
# Conventionally 'private' variables
_name = 'aPlugin'
_defaults =
property: 'value'
_debug = (args) ->
console.log args
return
# Plugin constructor
Plugin = (element, options) ->
@element = element
@options = $.extend true, {}, _defaults, options
@init()
return
# Initialization
Plugin.prototype.init = () ->
# Initialization logic here
_debug(@element) unless typeof(@element)=='undefined'
return
# Plugin wrapper, allowing for multiple instances
# and chainability
$.fn[_name] = (options) ->
return @.each (idx) ->
($.data @, 'plugin_' + _name
new Plugin @, options
) unless $.data @, 'plugin_' + _name
return
) jQuery, window, document
Here's the same code, when compiled (or transcompiled) to JavaScript.
(function() {
(function($, window, document) {
var Plugin, _debug, _defaults, _name;
_name = 'aPlugin';
_defaults = {
property: 'value'
};
_debug = function(args) {
console.log(args);
};
Plugin = function(element, options) {
this.element = element;
this.options = $.extend(true, {}, _defaults, options);
this.init();
};
Plugin.prototype.init = function() {
if (typeof this.element !== 'undefined') {
_debug(this.element);
}
};
$.fn[_name] = function(options) {
return this.each(function(idx) {
if (!$.data(this, 'plugin_' + _name)) {
$.data(this, 'plugin_' + _name);
return new Plugin(this, options);
}
});
};
})(jQuery, window, document);
}).call(this);
And, just to be clear, I am calling this plugin like this:
jQuery(document).ready(function($) {
$('#specialDiv').aPlugin({ aString: 'Hello world!', aNumber: 62742, aObject: { aString: 'Hello aPlugin!', aNumber: 6274210 } });
});
The options
argument in plugin call is irrelevant. That's for testing purposes.
I have two questions:
- In translated JavaScript, the intended code has been automatically wrapped in
(function(){}).call(this)
. I have never seen that before. What does it do? Is it safe? More yet, is it somewhat of a coding standard (since CoffeeScript is doing it). Something to add here: I am new to CoffeeScript so it might be a byproduct of a misplaced bracket or something. Still, it doesn't seem to hinder the operation. - When the code is executed, I get
<div id="specialDiv"> </div>
. In the code, you can see that I have calledconsole.log()
with caller (which should be a jQuery object) as argument. Where does it get unwrapped?
Thank you dearly for your time.
回答1:
CoffeeScript does it automatically to ensure that every non-explicitly-global variable is scoped as a local variable inside the scope of the wrapper function. An explicitly global variable may still be done with
window.myGlobal = 3
or, at the top level in CoffeeScript, with@myGlobal = 3
. This is a good way to write JavaScript too. So when you writex = 3
orwindow = { }
in CoffeeScript, these are treated as assignments to local variables rather than to global variables.Since
console
is not a local variable - it is not in the local-variables table of any enclosing lexical scope - the JavaScript fallback is to try it as a global variable, effectivelywindow.console
.
You do not need to shadow jQuery
, window
, and document
yourself when using CoffeeScript. In CoffeeScript, all non-explicitly-global variables are local: CoffeeScript will protect you in the same way that shadowing these variables in JavaScript would protect you.
来源:https://stackoverflow.com/questions/18106686/coffeescript-and-jquery-plugin-authoring