Actually you solved the problem already yourself, at least almost:
This is for any number of functions doing any number of things. I was thinking of switching plugin.has()
to do plugin.has("afk","check");
or something similar, so instead of chaining the functions, it's just in one function.
But passing variables to the check function would get tricky.
Well, there are basically two ways for this:
plugin_with_afk.has("afk","check").check(100); // "check" twice
plugin_with_afk.has("afk","check")(100); // "check" not twice
The first way is actually rather simple: simply return this
if the plugin has "afk", and otherwise return an object that has a no-op method check
:
Plugin.prototype.has = function(str, member){
if(this.things.indexOf(str) > -1) {
return this;
} else {
var tmp = {}
tmp[member] = function(){}
return tmp;
}
}
plugin_with_afk.has("afk","check").check(1); // has afk, check is there
plugin_without_afk.has("afk","check").check(2); // has no afk, check is no-op
plugin_without_afk.has("nope","check").check(3); // has nope, check is there
This has also the great advantage that you don't need to use any function wrapper and so on. However, you have to specify the used function twice, which would result in ReferenceError
if you accidentally used another name:
plugin_with_afk.has("afk","check").test(1); // oh oh
So what can you do against this? Create a simple function wrapper:
PluginWithFuncRet.prototype.has = function(str,member){
var self = this;
if(this.things.indexOf(str) > -1) {
return function(){
return self[member].apply(self, arguments);
}
} else {
return function(){};
}
}
plugin_with_afk.has("afk","check")(4); // calls check()
plugin_without_afk.has("afk","check")(5);// no-op
And that's it. Note that you should actually rename has
to use_if
or something similar, since it's now doing many things more than actually checking whether a component is there.
Complete code (demo)
var PluginBase = function(name, things){
this.name = name;
this.things = things;
}
/// First variant
var Plugin = function() {
this.constructor.apply(this, arguments);
}
Plugin.prototype.constructor = PluginBase;
Plugin.prototype.has = function(str,member){
if(this.things.indexOf(str) > -1) {
return this;
} else {
var tmp = {}
tmp[member] = function(){}
return tmp;
}
}
var plugin_with_afk = new Plugin("with afk", ["afk"]);
plugin_with_afk.check = function(val){
console.log("hi", val, this.name);
};
var plugin_without_afk = new Plugin("w/o afk", ["nope"]);
plugin_without_afk.check = function(val){
console.log("nope", val, this.name);
}
/// First variant demo
plugin_with_afk.has("afk","check").check(1)
plugin_without_afk.has("afk","check").check(2)
plugin_without_afk.has("nope","check").check(3)
/// Alternative
var PluginWithFuncRet = function(){
this.constructor.apply(this, arguments);
}
PluginWithFuncRet.prototype.constructor = PluginBase;
PluginWithFuncRet.prototype.has = function(str,member){
var self = this;
if(this.things.indexOf(str) > -1) {
return function(){
return self[member].apply(self,arguments);
}
} else {
return function(){}
}
}
plugin_with_afk = new PluginWithFuncRet("with afk",["afk"]);
plugin_with_afk.check = function(val){
console.log("Hi",val,this.name);
}
plugin_without_afk = new PluginWithFuncRet("w/o afk",["nope"]);
plugin_without_afk.check = function(val){
console.log("Nope",val,this.name);
}
/// Alternative demo
plugin_with_afk.has("afk","check")(4);
plugin_without_afk.has("afk","check")(5);
plugin_without_afk.has("nope","check")(6);
Result:
hi 1 with afk
nope 3 w/o afk
Hi 4 with afk
Nope 6 w/o afk