2

我正在尝试使用变量替换让 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];
4

6 回答 6

2

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

尝试这个,

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

编辑: 我相信您仅将其用于学习目的,而不是在生产站点上使用。

于 2012-09-03T05:42:44.450 回答
1

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

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

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

于 2012-09-03T05:41:15.013 回答
0

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

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

它很好地满足了我的要求。感谢大家的帮助。你们都很棒。

于 2012-09-03T09:20:20.603 回答
0

好吧,你所要求的远非最佳实践——所以我会给你一个不受欢迎的答案——使用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

于 2012-09-03T06:03:18.327 回答
0

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

 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');
于 2012-09-03T05:50:10.850 回答
0

我认为更简单的方法是使用 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 加上它的链接方法。

于 2018-06-27T01:57:50.763 回答