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