I am working on a parser combinator library in JavaScript. For that I want to create functions that can be called like any other functions, but also have member functions th
Although I know you asked for a solution without using Function.prototype, I wonder whether you had considered that you can chain conditionally-executing behaviors such that a Function.prototype function like double() will allow a co-existence of different behaviors depending on "class" instance...
// This could also be adapted to itself be on Function.prototype
function chainConditions () {
var args = arguments;
return function () {
for (var i=0, argl = args.length; i < argl; i++) {
var ret = args[i].apply(this, arguments);
if (typeof (ret) !== 'undefined') { // If you want to allow undefined to be returnable, you could instead add this to a try-catch and ignore those which throw exceptions or a certain exception
return ret;
}
}
};
}
Function.prototype.double = function () {
if (this.prototype instanceof Salutation) {
var that = this;
return function(x) {
return that(x) + ", " + that(x);
};
}
};
Function.prototype.double = chainConditions(
function () {
if (this.prototype instanceof Tennis) {
var that = this;
return function(x) {
return that(x) + ", " + that(x);
};
}
},
Function.prototype.double
);
function Salutation () {}
function Hello(x) {
return "Hello " + x;
}
function Goodbye(x) {
return "Goodbye " + x;
}
Goodbye.prototype = new Salutation();
function Tennis () {
}
function TennisPlayer (x) {
return x + ' serve';
}
TennisPlayer.prototype = new Tennis();
alert(TennisPlayer.double()('Forehand')); // Forehand serve, Forehand serve
alert(Goodbye.double()('Yellow Brick Road')); // Goodbye Yellow Brick Road, Goodbye Yellow Brick Road
alert(Hello.double()('Yellow Brick Road')); // does not work as we did not use Hello.prototype = new Salutation();
One should be able to abstract this even further by allowing one function to be used for the class type checking (e.g., grouping all Salutation methods on the Function.prototype together as one type check), and another to accept a list of methods keyed to their conditional behaviors.
While it uses its own API, it is fairly non-obtrusive and can even be made to work with existing methods on the Function.prototype which do not play along by throwing an exception (just be sure to include any pre-existing methods last).