5

文字列を使用してオブジェクトからメソッドを呼び出すことは可能ですか?

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
4

3 に答える 3

4

アップデート

これが私の最終的な実用的な答えです:
コンソールでこのコードを実行した後

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

これは、任意のオブジェクトで使用するのと同じ基本原則です (JS では、関数はすべてそれ自体がオブジェクトであり、jQuery オブジェクトもオブジェクトであることを思い出してください)。これは、プロパティとまったく同じ方法でメソッドにアクセスできることを意味します。

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

したがって、文字列を分割し、オブジェクト プロパティのようにメソッド名を使用するだけで、準備完了です。

覚えておいてください: eval ハンマーしかない場合、すべてが親指のように見えます。
ブレンダン・アイヒ


複数の引数が何らかのメソッドに渡される可能性がある場合は、それを回避することもできます(私は思います-まあ:ロジックは指示しますが、かなり遅く、ロジックはジンによってかなりひどいものになっています) :

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メソッド内のオブジェクトを指します)、呼び出されたメソッドに渡される引数の配列が渡されます。

于 2012-08-28T20:05:45.320 に答える
1

次のいずれかの方法を使用する必要があります。

  • 申し込み

    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()'
于 2012-08-28T20:40:06.280 に答える
0

Evalはあなたがやりたいことをします。ただし、やりたいことをしてはいけないので、評価は悪です。

JavaScriptのeval関数を使用するのはなぜ悪い考えですか?

于 2012-08-28T20:00:30.017 に答える