-
Notifications
You must be signed in to change notification settings - Fork 2
Patterns
On this page we want to collect common patterns where you normally use non-rethink.js-stuff like prototype
.
Let's start with the old way of doing JS.
// standard js
function User(name) {
this.name = name;
}
User.prototype.greet = function(greeting) {
console.log(this.name + ' says "' + (greeting || 'hi!') + '"')
}
var john = new User('John');
john.greet('howdy!'); // logs 'John says "howdy!"' to console
So how can we do this without prototype
and new
.
// rethink.js
function User(name) {
var user = {
name: name
}
user.greet = function(greeting) {
console.log(user.name + ' says "' + (greeting || 'hi!') + '"')
}
return user;
}
var john = User('John');
john.greet('howdy!'); // logs 'John says "howdy!"' to console
Pretty straight forward, right? You can hand over the user.greet
-method as is as a callback, no binding needed. Downside of this is that's it's slower than the upper version. This only kicks in, if you have a lot of items to construct. However, if you're forced to bind the this
-pointer performance of prototype-based js becomes slower. In rethink.js you never need to bind a this
-pointer.
We are currently working on a more meaningful performance test. We think the performance loss is not as high in real world use cases since using the constructed instances takes greater space than constructing them.
Again, here is the standard way of doing JS.
// standard js
function User(name) {
this.name = name;
}
User.prototype.greet = function(greeting) {
console.log(this.name + ' says "' + (greeting || 'hi!') + '"')
}
function Pirate(name) {
User.call(this, name);
}
Pirate.prototype = Object.create(User.prototype)
Pirate.prototype.greet = function() {
return User.greet.call(this, 'Aye!')
}
var john = new Pirate('John');
john.greet(); // logs 'John says "aye!"' to console
And now the version without prototype
and new
.
// rethink.js
function User(name) {
var user = {
name: name
}
user.greet = function(greeting) {
console.log(user.name + ' says "' + (greeting || 'hi!') + '"')
}
return user;
}
function Pirate(name) {
var pirate = User(name);
var superGreet = pirate.greet;
pirate.greet = function() {
superGreet('Aye!');
};
return pirate;
}
var john = Pirate('John');
john.greet(); // logs 'John says "Aye!"' to console
The readability has much improved here. The performance is also worse here but only matters when you create a lot (>1000) of items. Also when you use bind rethink is again faster.
Mixins are a common way to encapsulate functionality. With rethink.js mixins are pretty easy to achieve:
function Saveable(thing) {
thing.save = function() {
// code to save the thing
};
}
function User(name) {
var user = {
name: name
};
Saveable(user);
}
var john = User('John');
john.save(); // saves john
In standard javascript you can use instanceof
to check, what kind of object you deal with. Since we don't use prototypes
here, we can't rely on instanceof
here. There a few possibilities to allow the type checking.
The simplest is to annotate a type property on every object.
function User(name) {
var user = {
type: 'user',
name: name
};
}
var john = User('John');
john.type === 'user'; // true
john.type === 'tree'; // false
An other way would be to set a boolean property to the object:
function User(name) {
var user = {
isUser: true,
name: name
};
}
var john = User('John');
john.isUser; // true
john.isTree; // undefined and therefore falsey