JavaScript repetitive delegate creation
I'm creating a small wrapper for HTML5 canvas, and one thing I'm doing is returning self/this from each of my wrapped methods to make easy call chaining.
For lack of a better name i'm calling my wrapper C开发者_如何学编程anvas. It basically wraps the canvas and context together.
One thing I did is add the below methods to the Canvas.prototype
Canvas.fn = Canvas.prototype = {
save: function () { this.ctx.save(); return this; },
restore: function () { this.ctx.restore(); return this; },
scale: function (x, y) { this.ctx.scale(x, y); return this; },
rotate: function (angle) { this.ctx.rotate(angle); return this; },
translate: function (x, y) { this.ctx.translate(x, y); return this; },
transform: function (a,b,c,d,e,f) { this.ctx.transform(a,b,c,d,e,f); return this; },
Is there an easier way to add these methods using some delegate? Maybe with an array or the function names? Note that some methods take arguments and I want to pass them as is to the actual self.ctx method.
Something like this?
var functionNames = ['save', 'restore', 'scale', 'rotate', 'translate', 'transform'];
for(var i = 0; i < functionNames.length; i++) {
(function(funcName) {
this[funcName] = function() {
this.ctx[funcName].apply(this.ctx, arguments);
return this;
};
)(functionNames[i]);
}
Similar to Eric's answer, also based on http://seewhatever.de/blog/?p=440:
function CanvasWrapper(canvas)
{
// Call this with new ... or not
if(!(this instanceof CanvasWrapper)){
return new CanvasWrapper(canvas);
}
var self = this,
ctx = canvas.getContext('2d'),
props = [
'fillStyle', 'strokeStyle'
// ...
],
meths = [
'fillRect', 'strokeRect', 'clearRect',
'beginPath', 'closePath',
'moveTo', 'lineTo', 'arc',
'stroke'
// ...
],
nonChainableMeths = [
'createLinearGradient'
],
i, prop, meth;
// Create and set jQuery-like property accessors
// With no arguments they return the prop value
// With one argument they set the prop value and return self
function createAccessor(ctx, prop, self)
{
return function(){
if(arguments.length == 1)
{
ctx[prop] = arguments[0];
return self;
}
else
{
return ctx[prop];
}
}
}
for(i = 0; i < props.length; ++i)
{
prop = props[i];
self[prop] = createAccessor(ctx, prop, self);
}
// Create and set chainable delegate methods
function createDelegate(ctx, meth, self)
{
return function(){
ctx[meth].apply(ctx, arguments);
return self;
}
}
for(i = 0; i < meths.length; ++i)
{
meth = meths[i];
self[meth] = createDelegate(ctx, meth, self);
}
// Create and set non-chainable delegate methods
function createNCDelegate(ctx, meth, self)
{
return function(){
return ctx[meth].apply(ctx, arguments);
}
}
for(i = 0; i < nonChainableMeths.length; ++i)
{
meth = nonChainableMeths[i];
self[meth] = createNCDelegate(ctx, meth, self);
}
return self;
}
A continuation of Eric's answer that does work is given below:
var funs = ['save', 'restore', 'scale', 'rotate', 'translate',
'transform'];
var f;
for(var i = 0; i < funs.length; i++) {
f = funs[i];
self[f] = new Function("this.ctx." +
f + ".apply(this.ctx, arguments); return this;");
}
But I do not like the use of the Function
constructor and that my function is a made from a string.
精彩评论