I am just beginning to learn Coffeescript and cannot find a definite answer to why I should use
class Model extends Backbone.Model
urlRoot: '//some/url'
compiles to
Model = (function(_super) {
__extends(Model, _super);
function Model() {
_ref = Model.__super__.constructor.apply(this, arguments);
return _ref;
}
Model.prototype.urlRoot = '//some/url';
return Model;
})(Backbone.Model);
as opposed to
Model = Backbone.Model.extend
urlRoot: '//some/url'
compiles to
var Model = Backbone.Model.extend({
urlRoot: '//some/url'
});
The main reason I am asking is because the former is used in nearly all examples I have looked at. However, it creates 'much' more bloat when compiled as opposed to the latter. I did read this question, but the answers seem to differ.
Since you're asking just about the bloat, let's have a look at some code.
Backbone.Model.extend
If you open up the Backbone source code, you'll see the extend
function is the following:
var extend = function(protoProps, staticProps) {
var parent = this;
var child;
if (protoProps && _.has(protoProps, 'constructor')) { // _.has comes from
child = protoProps.constructor; // underscore, even
} else { // more 'bloat'
child = function(){ return parent.apply(this, arguments); };
}
_.extend(child, parent, staticProps); // more underscore
var Surrogate = function(){ this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate;
if (protoProps) _.extend(child.prototype, protoProps);
child.__super__ = parent.prototype;
return child;
};
When we call
var Model = Backbone.Model.extend({urlRoot: '//some/url' });
we get something like:
// Create new constructor which calls the parent constructor
var Model;
if (({}).hasOwnProperty.call({urlRoot: '//some/url' }, 'constructor') {
// this is false so...
} else {
Model = function(){ return Backbone.Model.apply(this, arguments); };
}
// Set up prototype chain
var Surrogate = function(){ this.constructor = model; };
Surrogate.prototype = Backbone.Model.prototype;
Model.prototype = new Surrogate;
// Add properties to the child prototype
// Same as:
// Model.prototype.urlRoot = '//some/url';
_.extend(Model.prototype, { urlRoot: '//some/url' });
// Set the magical __super__ property
Model.__super__ = Backbone.Model.prototype;
extends
Compare that with the CoffeeScript code. You will see that when you use extends
a magical function called __extends
gets added to the start of your file, which (when formatted) looks like:
__extends = function(child, parent) {
for (var key in parent) {
if (__hasProp.call(parent, key))
child[key] = parent[key];
}
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
return child;
};
which is combined with the generated JS:
var Model = (function(_super) {
__extends(Model, _super);
function Model() {
_ref = Model.__super__.constructor.apply(this, arguments);
return _ref;
}
Model.prototype.urlRoot = '//some/url';
return Model;
})(Backbone.Model);
When we call
Model extends Backbone.Model
urlRoot: '//some/url'
we get something like:
// Create new constructor which calls the parent constructor
var Model = function () {
return Model.__super__.constructor.apply(this, arguments);
}
// Copy static properties from Backbone.Model to Model
for (var key in Backbone.Model) {
if (__hasProp.call(Backbone.Model, key))
Model[key] = Backbone.Model[key];
}
// Set up prototype chain
function ctor() { this.constructor = Model; }
ctor.prototype = Backbone.Model.prototype;
Model.prototype = new ctor();
// Add properties to the child prototype
Model.prototype.urlRoot = '//some/url';
// Set the magical __super__ property
Model.__super__ = Backbone.Model.prototype;
They look pretty similar don't they?
CoffeeScript is just JavaScript. If you are already using Backbone and want to avoid adding in the __extends
function in your generated source, then use Backbone.Model.extend
. If you want to avoid adding in Backbone all together then extends
does practically the same thing. The reason that so many examples don't use the latter is that Backbone is not required to use CoffeeScript - it just wouldn't make sense to have an example which relies on an external library.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With