7

解决方案:没有。你不能这样做。用 && 链接命令并完成它。

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

的背景:

好的,所以我对代码感到恐惧。但我试图通过编写能让我的生活稍微轻松一点的东西来拖延。而我的边缘,我的意思是微观上。所以基本上,我的整个项目都是基于对象和插件的。(插件是包含对象的附加 .js 文件。例如,afk.js 看起来像这样:

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

等等等等。通过加载那个 js 文件,我可以访问 afk 对象和其中的所有函数。可能效率不高,但它可以工作,并且可以更容易地弄清楚哪些功能正在做什么。

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

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

按预期工作。除非没有afk插件,否则会抛出“false has no method check”的明显错误。

就是这样。有任何想法吗?另外,如果您对任何事情有任何疑虑,请告诉我。我知道我做错了很多事情/效率低下,当我弄清楚时修复它们很好。

4

8 回答 8

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();
于 2013-04-15T17:34:32.590 回答
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;
}
于 2013-04-15T17:40:26.877 回答
1

完成这项工作的一种简短而肮脏的方法是使用 && 运算符。

var x = {};

x.afk && x.afk();

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

x.afk && x.afk();

虽然不是您的最佳广泛解决方案。

于 2013-04-15T17:50:01.660 回答
1

在当前的 ECMAScript 规范中,.check()变成无操作(以及可能存在于不存在的插件上的任何其他方法)是不可能的,因为您不能因为您发现可移植地访问未定义对象的未定义属性。

提议的“直接代理” ECMAScript API 似乎可以解决这个问题,但它还没有标准化。我还怀疑以这种方式代理您的代码效率不高,因为您(AIUI)必须让您的.has()函数返回一个捕获代理对象,然后必须为每个“错过”的函数调用做真正的工作。恕我直言,简单地确保条件代码根本不会运行会好得多。

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

plugin.if("afk", function() {
    // put conditional code here
});
于 2013-04-15T18:36:19.033 回答
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");then 它会检查引导函数的数据,如果找不到,则返回到 basic.boot();,并调用正确的函数。我可以调用数据函数并传递变量,例如在保存数据的情况下,$("save",data);

如果这是一个愚蠢的想法,请随时告诉我!但到目前为止它对我有用<3

于 2013-04-16T06:17:06.150 回答
0

它不适用于所有浏览器,但我认为您可以创建一个虚拟类,用于__noSuchMethod__始终返回自身,而不是在调用不存在的方法时抛出错误。看到这个问题

我不知道这适用于哪些浏览器,我的总体印象是“不多”。

于 2013-04-15T18:02:10.860 回答
0

实际上你已经自己解决了这个问题,至少几乎是:

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

好吧,基本上有两种方法:

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

第一种方法实际上相当简单:this如果插件有“afk”则简单地返回,否则返回一个具有无操作方法的对象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

就是这样。请注意,您实际上应该重命名hasuse_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
不 3 w/o afk
嗨 4 与 afk
不 6 w/o afk
于 2013-04-15T21:08:06.277 回答
0

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

于 2013-04-15T18:13:46.717 回答