Javascript:函数链接

解决办法:不。 你不能这样做。 用&&​​链命令并用它来完成。

tl; dr:in random.function("blah").check() ,如果function("blah")返回false,我该如何忽略check() 或者这甚至有可能?

的背景:

好的,所以我很惊讶于代码。 但是我试图通过编码来让事情变得轻松一点,从而拖延。 而我的意思是,我的意思是微观上的。 所以基本上,我的整个项目是基于对象和插件。 (插件是包含一个对象的额外的.js文件,例如,afk.js看起来像这样:

 global.afk = function(){}; afk.check = function(){ ... }; 

通过加载该js文件,我可以访问afk对象及其中的所有函数。 可能效率不高,但它的工作原理和它确定什么function在做什么更容易。

回到拖延位。 因为我不知道哪些插件被加载,在一些共享的核心.js文件中,有这些条件语句: if (plugin.has("afk")) { afk.check(); }; if (plugin.has("afk")) { afk.check(); }; 然而,我感到无聊,使plugin.has()返回实际的对象,而不是“真”,所以我可以这样做:

 plugin.has("afk").check(); 

按预期工作。 除非没有afk插件,这会引发“false没有方法检查”的明显错误。

那就是这样。 有任何想法吗? 另外,如果您有任何疑虑,请告诉我。 我知道我做了很多错误/效率低下的事情,而且在我弄明白的时候修正它们是很好的。

返回的对象应该有这个function,否则你会得到一个错误。 你可以做的是做一个基本的对象types,它总是返回。 当你返回它时,它有一个空的函数,不会产生错误。

就像是:

 var baseObj = function(){ this.afk = function(){ return this; } this.check = function(){ return false; } }; var advObj = new baseObj(); advObj.afk = function(){ // extended func return new baseObj(); } var a = new advObj(); a.afk("test").check(); 

所以jQuery有点像这样:

$(plugin) – >返回一个像对象的集合
.has("afk") – >过滤内部集合,并返回集合
.check() – >对此集合执行的操作

那么让我们举个小例子吧:

 function Wrapper(ele) { // make our collection this.coll = [ ele ]; // function to filter this.has = function(filter) { this.coll = this.coll.filter(function(e) { return e === filter; }); // we return ourself for chaining return this; }; // function to execute on ourself this.check = function() { // returns actual value return this.coll.length; }; } var $ = function(ele) { // wrapper around the `new` syntax return new Wrapper(ele); }; console.log($('jan').has('jan').check()); // gives 1 console.log($('pietje').has('jan').check()); // gives 0 

很酷的事情是,你现在可以通过扩展原型扩展你的Wrapper对象从外部文件:

 Wrapper.prototype.hasNot = function(filter) { /* do magic */ return this; } 

在目前的ECMAScript规范中,将.check()转换为no-op(以及任何其他可能存在于不存在的插件上的方法)是不可能的,因为你不能find可移植的未定义对象的未定义属性。

拟议的“直接代理” ECMAScript API似乎可以解决这个问题,但它还没有标准化。 我也怀疑用这种方法代理你的代码效率不高,因为你(AIUI)必须让你的.has()函数返回一个陷阱代理对象,然后必须为每一个“错过”的函数调用做真正的工作。 恕我直言,只是确保条件代码永远不会运行。

所以,除了其他地方提出的&&方法之外,我所能提供的只是:

 plugin.if("afk", function() { // put conditional code here }); 

做这个工作的简短和肮脏的方法是使用&&操作符。

 var x = {}; x.afk && x.afk(); x.afk = function () { console.log("I exist!"); }; x.afk && x.afk(); 

不是你最佳的宽范围解决scheme。

它不适用于所有的浏览器,但我想你可以创build一个虚拟类,使用__noSuchMethod__总是返回自己而不是在调用不存在的方法时抛出错误。 看到这个问题 。

我不知道这是什么浏览器,我的总体印象是“不是很多”。

哦你好。 节点代理看起来很有前途。 实际上我对此一无所知,但这听起来像是应该让你做这种事情。

其实你已经自己解决了这个问题,至less差不多:

这是任何数量的function做任何事情。 我正在考虑切换plugin.has()来做plugin.has("afk","check"); 或类似的东西,所以,而不是链接function,它只是在一个function。 但是将variables传递给检查函数会变得棘手。

那么,基本上有两种方法:

 plugin_with_afk.has("afk","check").check(100); // "check" twice plugin_with_afk.has("afk","check")(100); // "check" not twice 

第一种方法其实很简单:只要插件有“afk”就返回this ,否则返回一个没有op-op方法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 

这也有很大的好处,你不需要使用任何函数包装等。 但是,您必须指定使用的函数两次,如果您不小心使用了另一个名称,则会导致ReferenceError

 plugin_with_afk.has("afk","check").test(1); // oh oh 

那么你能做些什么呢? 创build一个简单的函数包装器:

 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 

就是这样。 请注意,实际上您应该重命名为use_if或类似的东西,因为现在做更多的事情比实际检查组件是否在那里。

完整的代码(演示)

 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); 

结果:

 嗨1 afk
 nope 3 w / o afk
嗨4与afk
没有6 w / o afk

所以这就是我想出来的,并最终结束了使用。
比创造一个虚拟包装Wrather,我决定加载所有
插入到主包装。 所以现在,阿富汗人是plg.afk,就像
所有其他插件。 这让我写这个包装:

 global.& = function(a,b) { var x,y,z;if (!a) return false; //if nothing, return false. if (a.indexOf(".") < 0) { //if value has no "." if (plg["data"][a]) { x = ["data",a]; } //use data function if exists else { x = ["basic",a]; } //else assume it's a basic function } else { //or if it does contain "." (such as my example, afk.check) x = a.split(".") //define the plugin, and the function as an array. } y = x[0],z = x[1]; //define the plugin,function as variables. if (!plg[y]) { return false; } //return if plugin doesn't exist. if (!plg[y][z]) { return false; } //return if function doesn't exist. if (!b) { plg[y][z](); } //if no variable, call raw function return plg[y]z[](b); //return function, passing an optional variable. } 

所以这个工作! 我可以调用$(“afk.check”); 它基本上是这样做的:

 if (plugin.has("afk") && afk.hasOwnProperty("check")) { afk.check(); }; 

:d

我可以传递variables,并使用基本function的快捷方式。

例如,如果我调用$("boot"); 然后检查引导函数的数据,当它没有find时,返回到basic.boot();并调用正确的函数。 我可以调用数据函数并传递variables,如保存数据$("save",data);

随意让我知道这是一个愚蠢的想法! 但到目前为止,它为我工作<3