【问题标题】:Javascript chaining and variable substituteJavascript 链接和变量替换
【发布时间】:2012-09-03 05:36:31
【问题描述】:

我正在尝试使用变量替换让 javascript 链接工作。无法让它工作。帮助表示赞赏。

var Class = function() {

 this.one = function() {
   alert('one');        
   return this;
 }

 this.two = function() {
   alert('two');
   return this;
 }

 if (this instanceof Class) {
    return this.Class;
 } else {
    return new Class();
 }

}

var test = new Class();
// this works
test.one().two();

var func = '.one().two()';
// want to make this work
test[func];

【问题讨论】:

  • 根据字符串中的名称调用函数被认为是一种不好的做法。字符串中的链接名称 - 不好的做法 x2。这确实使这种代码支持变得痛苦和昂贵。
  • 感谢您的建议。我正在使用促进函数链接的 Node.Js 验证库。我希望链接基于某些参数是动态的。上面的例子只是说明我想要实现的目标。
  • @MeUnagi - 其他插件(?)或示例代码如何处理相同的问题?例如,在 Asp.net MVC 验证中,这些是字符串和函数之间的清晰映射,并且您在此处描述的机制是自动完成的(包括参数)

标签: javascript chaining method-chaining


【解决方案1】:

没有名为'.one().two()'的函数

试试这个,

test['one']()['two']();

编辑: 我相信您只是将其用于学习目的,而不是在生产现场。

【讨论】:

  • 我同意,我 Unagi 希望更改现有代码以使其正常工作。
  • “我正在尝试使用变量替换让 javascript 链接工作。”。在这种情况下,变量 = 动态。这是硬编码的。
  • 感谢您的闪电回复。抱歉,我不太清楚我在找什么。函数链字符串根据特定条件动态构造。每个条件都将函数添加到链接字符串。函数链可以是 'one().two()' 或 'one().two().three()'。
【解决方案2】:

强烈不推荐。您可能想尝试使用数组:

var funcs = ['one','two'];
for(var i = 0; i < funcs.length; i++) {
  test[funcs[i]]();
}

然后你可以把它包装成一个小函数:

function callChain(obj, funcs)
{
  for(var i = 0; i < funcs.length; i++) {
    obj[funcs[i]]();
  }
  return obj;
}

编辑:如果您的链存储为字符串:.one().two(),则可以使用 split & string 函数动态生成数组。

【讨论】:

    【解决方案3】:

    好吧,你所要求的远非最佳实践 - 所以我会给你一个不受欢迎的答案 - 使用 eval
    如果您的输入是作为字符串的一般代码,那么您实际上没有任何其他选择(特别是当您的函数有参数时 - .one(1 + 0.5).two(new Date()))。

    例如,在您的Class 中添加:

    this.excecute = function(commands){
        eval('this' + commands);
    };
    

    然后:

    test.excecute('.one().two(4 * 5)');
    

    工作示例:http://jsbin.com/ipazaz/1/edit

    这会发出警告“eval is evil”(我认为是 jslint)——但我不相信函数是邪恶的。

    更糟糕的是,如果你有字符串 'one(); two(4 * 5);' 怎么办?
    你也可以使用with

    this.excecute = function(commands){
        with(this){
            eval(commands);
        }
    }; 
    

    这里有一个额外的警告:“不要使用 'with'” - 他们今天真的对我们有什么不满,不是吗?

    工作示例:http://jsbin.com/ipazaz/2/edit

    【讨论】:

    • 请大家在投反对票之前 - 这里的假设是我们可能将 code 作为函数的参数,而不仅仅是字符串 "one one two one"
    【解决方案4】:

    感谢大家的及时帮助。我最终接受了 Ben Rowe 的建议。

    var funcs = ['one','two'];
       for(var i = 0; i < funcs.length; i++) {
       test[funcs[i]]();
    }
    

    它非常符合我的要求。感谢大家的帮助。你们都很棒。

    【讨论】:

      【解决方案5】:

      您可以在构造函数中添加一个方法:

       this.chain = function chain(){
         if (arguments.length && /\./.test(arguments[0])) {
          return chain.apply(this,arguments[0].split('.'));
         }
         var methods = [].slice.call(arguments),
             method = methods.shift();
         if(this[method] instanceof Function){
          this[method].call(this);
         }
         if (methods.length){
          chain.apply(this,methods);
         }
         return this;
       }
       // now you could do something like:
       test.chain('one.two.one.two.two');
      

      或扩展Object.prototype

      Object.prototype.chain = function chain(){
         if (arguments.length && /\./.test(arguments[0])) {
          return chain.apply(this,arguments[0].split('.'));
         }
         var methods = [].slice.call(arguments),
             method = methods.shift();
         if(this[method] && this[method] instanceof Function){
          this[method].call(this);
         }
         if (methods.length){
          chain.apply(this,methods);
         }
         return this;
      };
      // usage
      ({one:function(){console.log('I am one');},
        two:function(){console.log('I am two');}})
       .chain('one.two.one.one.two.two.two.one.two');
      

      【讨论】:

        【解决方案6】:

        我认为更简单的方法是使用 javascript 的数组 reduce 函数。 对于我正在编写的一些动态 jquery 内容,我需要它。一旦你有了一系列可链接的方法,你就可以轻松地执行以下操作。

        var methods = ['next', 'child', 'parent'];
        
        var element = methods.reduce(function(method){
            return $(selector)[method]();
        });
        
        console.log(element) //works! as all method names in methods array are applied and returned each iteration.
        

        对于我来说,接受的答案对我不起作用,它似乎只返回传递的 obj 而不是 obj 加上它的链式方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-04-15
          • 2016-08-15
          • 2011-11-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多