Skip to content

Instantly share code, notes, and snippets.

@x7c1
Created December 23, 2011 09:23
Show Gist options
  • Select an option

  • Save x7c1/1513704 to your computer and use it in GitHub Desktop.

Select an option

Save x7c1/1513704 to your computer and use it in GitHub Desktop.
mixin in javascript
// using node.js
exports.mixin = new function(){
function mixin(klass, trait){
var new_class = function(){};
new_class.prototype = new function(){
var f = function(){}
f.prototype = klass.prototype;
return extend(new f, trait);
};
return new_class;
}
return function(klass){
return [].slice.call(arguments, 1).reduce(mixin, klass);
}
}
function extend(dst, src) {
for (var key in src) {
if (src.hasOwnProperty(key))
dst[key] = src[key];
}
return dst;
}
// node example_test.js
var assert = require('assert');
var mixin = require('./example.js').mixin;
var TraitA = {
getA: function(){ return "A" }
};
var TraitB = {
getB: function(){ return "B" }
};
var ClassX = function(){}
ClassX.prototype = {
getX: function(){ return "X" }
};
var ClassY = function(){}
ClassY.prototype = {
getY: function(){ return "Y" }
};
var ClassX_with_A = mixin(ClassX, TraitA);
var ClassX_with_A_B = mixin(ClassX_with_A, TraitB);
var x = new ClassX_with_A_B;
assert.equal(x.getX(), "X");
assert.equal(x.getA(), "A");
assert.equal(x.getB(), "B");
var ClassY_with_A_B = mixin(ClassY, TraitA, TraitB);
var y = new ClassY_with_A_B;
assert.equal(y.getY(), "Y");
assert.equal(y.getA(), "A");
assert.equal(y.getB(), "B");
ClassX_with_A_B.prototype.getAB = function(){
return "AB";
};
// method defined after "new" is callable
assert.equal(x.getAB(), "AB");
// ClassX is not affected with
// methods added to the prototype of newly generated class
assert.equal(ClassX.prototype.getAB, undefined);
ClassX.prototype.getX2_defined_dynamically = function(){
return "X2";
};
// method defined dynamically in original ClassX
// is callable by prototype-chain
assert.equal(x.getX2_defined_dynamically(), "X2");
TraitA.getA2_defined_dynamically = function(){
return "A2";
};
// cannot call a method defined after "new" in Trait (not cool)
assert.equal(x.getA2_defined_dynamically, undefined);
// can use original "instanceof" of javascript
assert.equal(x instanceof ClassX, true);
assert.equal(x instanceof ClassX_with_A, true);
assert.equal(x instanceof ClassX_with_A_B, true);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment