In fact, you already solved the problem yourself, at least almost:
This is for any number of functions that perform any number of things. I was thinking of switching plugin.has() to plugin.has("afk","check"); or something similar, so instead of a chain of functions, it's just one function. But passing variables to the validation function will be difficult.
Well, there are two ways to do 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 quite simple: just return this if the plugin has "afk" and otherwise returns an object that has a no-op check method:
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 also has the great advantage that you do not need to use any kind of shell functions, etc. However, you need to specify the function used twice, which will lead to a ReferenceError if you accidentally used a different 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);
What is it. Note that you really have to rename has to use_if or something similar, as it now does a lot of things more than actually checks to see if there is a component.
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