jashkenas / jashkenas/backbone

Embrace prototypes

Open
#4,245 12 comments 1 reaction 0 assignees View on GitHub
question
Dominant language
JavaScript
Stars
28.1k
Forks
5.3k
PR merge metrics
No merged PRs in 30d

Description

The ES6 class emulation convention doesn't sit well with Backbone, mostly because it provides no convenient way to set non-function prototype properties. In fact, in my opinion, the ES6 class emulation convention doesn't sit well in general for this same reason. On top of that, classes don't sit well with JavaScript, anyway. I'm not the first to say this; consider [Walker 2014](https://walkercoderanger.com/blog/2014/04/what-coffeescript-should-have-been/#embrace-prototypes) and [Crockford 2008](https://crockford.com/javascript/prototypal.html). I consider #4079 a symptom of classes not sitting well.

Therefore, in Backbone version 2, rather than adapting the library to ES6 classes, I would like to do away with classes entirely and embrace prototypes instead. That would mean that instead of the following in Backbone 1,

```js
import { extend } from 'underscore';
import { Model } from 'backbone';

const CustomModel = Model.extend({
idAttribute: '_id',
// ...
});

// or

class CustomModel extends Model { /*...*/ }
extend(CustomModel.prototype, {
idAttribute: '_id',
};

// in either case:
const aCustomModelInstance = new CustomModel(attributes, options);
```

we would be writing something like the following in Backbone 2:

```js
import { model } from 'backbone';

const customModel = model.extend({
idAttribute: '_id',
// ...
});

const aCustomModelInstance = customModel.construct(attributes, options);
```

where `model` is an object that serves as a prototype, instead of a function that emulates a class.

`model.extend(protoprops)` (and `collection.extend`, etcetera) would default to just being a shorthand for `Object.create(model, protoprops)`. (I would likely use `_.create` instead of `Object.create`, but that is an implementation detail.) This method can still be overridden by plugins in order to enable things like shorthand syntax at prototype extension time.

`model.construct(attributes, options)` would first do `Object.create(model)` and then perform the same logic on the created instance as the current constructor. In fact, we could retain the old constructor and simply implement `model.construct` as `Object.create(model).constructor(attributes, options)`. This would enable people who really want to use class emulation to set `Model = model.constructor` and continue working in the old way.

In summary, the code would not necessarily change that much. It's just that the library exports prototypes instead of constructors, `extend` moves from the constructor to the prototype and there is a new `construct` method that replaces the `new` keyword. As a result, everyone using Backbone can seamlessly and interchangeably write their code in the same way, regardless of what particular flavor of class emulation they are using.

Feedback welcome. I'm not starting on Backbone 2 anytime soon, so there is plenty of time.

Contributor guide

Open the contributing guide

Research direction

Start by reviewing Backbone's current Model and collection APIs, especially extend and construction, against the prototype-based design described in the issue. Because no files or tests are identified and the proposal is for a future Backbone 2 redesign, completion would require an agreed design and implementation scope before coding can begin.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
frontend, web-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.