【问题标题】:Is it possible to call a method from an object using a string?是否可以使用字符串从对象调用方法?
【发布时间】:2012-08-23 09:31:22
【问题描述】:

是否可以使用字符串从对象调用方法?

var elem = $('#test');             //<div id="test"></div>
var str = "attr('id')";  

//This is what I'm trying to achieve
  elem.attr('id');                 //test

//What I've tried so far  
  elem.str;                        //undefined
  elem.str();                      //Object [object Object] has no method 'str'
  var fn = eval(str);              //attr is not defined
  eval(elem.toString()+'.'+str);   //Unexpected identifier

//Only solution I've found so far, 
//but is not an option for me 
//because this code is in a function 
//so the element and method call
//get passed in and I wouldn't know
//what they are
  eval($('#test').attr('id'));     //test

【问题讨论】:

  • 你试过了吗 alert(elem+'.'+str);
  • @AshirvadSingh - 显示[object Object].attr('id')
  • @Aby - 是的,我已经看到了。这适用于从字符串调用函数,但我希望从字符串调用对象的方法。

标签: javascript jquery string methods eval


【解决方案1】:

更新

这是我最终的有效答案:
在控制台中运行此代码后

theMethod = 'attr("id","foo")'.match(/^([^(]+)\(([^)]*)\)/);
jQuery('#post-form')[theMethod[1]].apply(jQuery('#post-form'),JSON.parse('['+theMethod[2]+']'));

post-form 元素现在有了新的 ID,完全没有问题。这适用于采用多个参数、单个参数或根本没有参数的方法。回顾:

theMethod = theInString.match(/^\.?([^(]+)\(([^)]*)\)/);
//added \.? to trim leading dot
//made match in between brackets non-greedy
//dropped the $ flag at the end, to avoid issues with trailing white-space after )
elem[theMethod[1]].apply(elem,JSON.parse('['+theMethod+']'));

这是我能想到的最安全、最可靠的方法,真的


你做过什么不要使用 EVAL

var theMethod = 'attr(\'id\')';
//break it down:
theMethod = theMethod.match(/^([^(]+)\(.*?([^)'"]+).*\)$/);
//returns ["attr('id')", "attr", "id"]
elem[theMethod[1]](theMethod[2]);//calls the method

这与您对 any 对象使用的基本原则相同(请记住,函数在 JS 中都是独立的对象 - 而 jQuery 对象也是对象)。这意味着可以以与属性完全相同的方式访问方法:

$('#foo').attr('id') === $('#foo')['attr']('id');

因此,只需将字符串分开,并像使用对象属性一样使用方法名称,就可以开始了。

请记住:当你只有评估锤时,一切看起来都像你的拇指。
Brendan Eich


如果有可能将多个参数传递给任何方法,您也可以按照自己的方式解决这个问题(我认为 - 好吧:逻辑决定了,但现在已经很晚了,逻辑被 Gin 打败了现在不好了):

theMethod = theMethod.match(/^([^(]+)\(([^)]+)\)$/);
//["attr('id','foo')", "attr", "'id','foo'"] --> regex must now match quotes, too
elem.theMethod[1].apply(elem,JSON.parse('['+theMethod[2]+']'));

这会将您正在处理的任何元素/对象的方法应用于自身,因此不会更改调用者上下文(this 仍将指向方法中的对象)并且它传递的参数数组将是传递给被调用的方法。

【讨论】:

  • 您不能可靠地在逗号上拆分参数,因为参数中可能还有其他逗号。 'func(greet("Elias", "Hi, how are you"), /(.*?),.*/)'
  • 公平地说,这只是在黑暗中的一次野刺,需要一点工作,少喝很多酒,不过我可以写一个表达式来可靠地拆分参数。不过,在这种情况下,您可以只使用JSON.parse('["foo","bar"]')elem,theMethod[2].apply(elem,JSON.parse('['+theMethod[2]+']')); 可以正常工作,不是吗?哈,刚想起来,比分裂还要好……我正在编辑我的答案!杜松子酒万岁!
  • JSON 数据仅代表可能出现的可能语法的一小部分。 undefined、标识符、正则表达式、匿名函数和函数调用之类的东西会破坏它。我认为这将归结为解析 JavaScript 或使用 eval
  • 您从一个包含函数定义/声明的字符串开始的可能性有多大,然后您需要将其作为参数传递给 jQ 方法?如果这个问题的答案是非常,那么我很抱歉,但是你解决问题的方式有问题......但这正是我的感受,是的,然后 eval 变成几乎是必需品。虽然你正在跳入 eval 最危险的用法:eval-ing 来创建新函数……哎哟
  • 当你在这个网站上时,在你的控制台中输入eval('$ = function(){return null;}') 并检查杀死jQuery会丢失哪些功能......
【解决方案2】:

您应该使用以下方法之一:

  • 申请

    var result = function.apply(thisArg[, argsArray]);

  • 打电话

    var result = fun.call(thisArg[, arg1[, arg2[, ...]]]);

示例如下:

var Sample = function() {
var that = this;

this.sampleMethod = function() {
    return alert("Hello!");
};

this.sampleMethod2 = function(){

    that["sampleMethod"].apply(that);
};  
};

var objImpl = new Sample();

objImpl.sampleMethod2(); //you will get a message from 'sampleMethod()'

【讨论】:

  • 你是从哪里开始的,格式类似于.attr('arg','arg')
  • that["sampleMethod"].apply(that);
  • 我想你误会了。 OP 正在寻找一种无 eval 的方法来从像 var someStr = 'setAttr("id","foobar")'; 这样的字符串开始,并使用它来调用 jQuery 对象上的 setAttr 方法并正确传递参数,你的不这样做
  • 另一件事:你为什么使用that,而不是这个?我在这里看不到/that 的意义,在这两种方法中,this 无论如何都会引用Sample 对象
  • 我同意,在特定情况下,'that' 是多余的。 'Sample' 类包含例如 jQuery 事件绑定 ($(document).click(function(){...});) 来调用 'Sample' 类的公共函数时是实际的。
【解决方案3】:

Eval 做你想做的事。然而,eval 是邪恶的,因为你不应该做你想做的事。

Why is using the JavaScript eval function a bad idea?

【讨论】:

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