解决方案:不。你不能这样做。带&&的链命令并完成它。
tl; dr:在random.function("blah").check()
中,如果check()
返回false,如何忽略function("blah")
?或者这甚至可能吗?
背景:
好的,所以我对代码很可怕。但是我试图通过编码使我的生活变得轻松的事情来拖延。而我的勉强,我的意思是显微镜。所以基本上,我的整个项目都是基于对象和插件。 (插件是包含对象的附加.js文件。例如,afk.js看起来像这样:
global.afk = function(){};
afk.check = function(){ ... };
等等。通过加载该js文件,我可以访问afk对象及其中的所有功能。可能效率不高,但它有效,它可以确定哪些功能更容易做到。
回到拖延位。因为我不知道加载了哪些插件,在一些共享核心.js文件中,有以下条件语句:if (plugin.has("afk")) { afk.check(); };
然而,我感到无聊并使plugin.has()
返回实际对象而不是'是',所以我可以这样做:
plugin.has("afk").check();
按预期工作。除非没有afk插件,否则会抛出“false not no method check”的明显错误。
就是这样。有任何想法吗?此外,如果您有任何疑虑,请告诉我。我知道我做了很多错误/效率低下的事情,当我想出来时修复它们很好。
答案 0 :(得分:1)
返回的对象应具有该功能,否则会出错。你可以做的是创建一个基本的Object类型,它总是被返回。与返回时相比,它具有空函数,不会产生错误。
类似的东西:
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();
答案 1 :(得分:1)
所以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;
}
答案 2 :(得分:1)
在当前的ECMAScript规范中,将.check()
转换为无操作(以及可能存在于不存在的插件上的任何其他方法)是不可能的,因为您无法找到未定义的undefined属性对象。
建议的"Direct Proxies" ECMAScript API似乎可以解决这个问题,但它还没有标准化。我还怀疑以这种方式代理你的代码并不是非常有效,因为你会(AIUI)必须让你的.has()
函数返回一个陷阱代理对象,然后必须为每个“错过的”函数调用做真正的工作。恕我直言,只需确保条件码永远不会运行。
所以,除了其他地方提出的&&
方法之外,我能提供的就是:
plugin.if("afk", function() {
// put conditional code here
});
答案 3 :(得分:0)
简单而肮脏的方法是使用&&和操作
var x = {};
x.afk && x.afk();
x.afk = function () { console.log("I exist!"); };
x.afk && x.afk();
不是最佳的广泛解决方案。
答案 4 :(得分:0)
它不适用于所有浏览器,但我认为您可以创建一个虚拟类,使用__noSuchMethod__
始终返回自身,而不是在调用不存在的方法时抛出错误。请参阅this question。
我不知道这会使用什么浏览器,我的总体印象是“不多”。
答案 5 :(得分:0)
哦,你好。 Node-proxy看起来很有希望。我实际上并不了解它,但听起来它应该让你做到这一点。
答案 6 :(得分:0)
实际上你已经解决了这个问题,至少差不多:
这适用于任何数量的功能。我正在考虑将
plugin.has()
切换为plugin.has("afk","check");
或类似的东西,因此它不是链接函数,而是在一个函数中。 但是将变量传递给check函数会变得棘手。
嗯,基本上有两种方法:
plugin_with_afk.has("afk","check").check(100); // "check" twice
plugin_with_afk.has("afk","check")(100); // "check" not twice
第一种方式实际上相当简单:如果插件具有“afk”,则返回this
,否则返回具有无操作方法的对象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
那么你能对此做些什么呢?创建一个简单的函数包装器:
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
就是这样。请注意,您实际上应该将has
重命名为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);
结果:
hi 1 with afk nope 3 w/o afk Hi 4 with afk Nope 6 w/o afk
答案 7 :(得分:0)
所以这就是我提出来的,最终最终使用了。
除了创建一个虚拟包装器之外,我决定加载所有的
插入主包装器。所以现在,afk是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
我可以传递变量。并使用基本功能的快捷方式。
例如,如果我调用$("boot");
,那么它会检查数据以获取启动函数,当它找不到启动函数时,将恢复为basic.boot();,并调用正确的函数。我可以调用数据函数并传递变量,例如在保存数据$("save",data);
如果这是一个愚蠢的想法,请随时告诉我! 但到目前为止,它对我有用&lt; 3