I've read through a lot of JavaScript mixin design patterns, but didn't found one that suits my needs. Most of what I've seen uses some extent function that copies methods of one object to the prototype of another. For value properties this works just like with a method, but it fails for properties which are objects itself, because just copying them means every instance of my class will point to the same object for this property.
I made a code example with a simple point class:
var Point = function ( x, y ) {
this.x = x;
this.y = y;
};
Point.prototype = {
constructor: Point,
print: function () {
console.log( this.x + this.offset[0], this.y + this.offset[1] );
}
};
The print function uses an offset property which I haven't declared yet, because it originates from a Transformable class I want to mixin into my Point class:
var Transformable = {
offset: [ 0, 0 ],
setOffset: function ( x, y ) {
this.offset[ 0 ] = x;
this.offset[ 1 ] = y;
}
};
To make the mixin I use some extent function like this:
var extent = function ( target, mixin ) {
for ( var property in mixin ) {
if ( !target.prototype[ property ] ) {
target.prototype[ property ] = mixin[ property ];
}
}
};
extent( Point, Transformable );
Now the code compiles and can be used:
var myPoint1 = new Point( 1, 2 );
myPoint1.setOffset( 5, 5 );
var myPoint2 = new Point( 1, 2 );
myPoint1.print();
myPoint2.print();
But it prints "6 7" both of the times, because the offset array used in myPoint2 is the same as in myPoint1.
So how can I achieve that every point gets its own offset array while still originating from the mixin? It should work for every object besides arrays as well, because when not for the simplicity of a short example I would use a vector class here instead.
Actually this answer accomplishes what I want, but as a further requirement I want to be able to still use the object literal syntax for adding the methods of the Point class:
Point.prototype = {
constructor: Point,
print: function () {...},
...
};
I am however flexible as to how the syntax for the mixin object might look like.