回答:
絶対に、積極的に他に選択の余地がないeval
限り使用しないでください。
すでに述べたように、次のようなものを使用するのが最善の方法です。
window["functionName"](arguments);
ただし、名前空間付きの関数では機能しません。
window["My.Namespace.functionName"](arguments); // fail
これは、次のようにする方法です。
window["My"]["Namespace"]["functionName"](arguments); // succeeds
それをより簡単にし、ある程度の柔軟性を提供するために、ここに便利な関数があります:
function executeFunctionByName(functionName, context /*, args */) {
var args = Array.prototype.slice.call(arguments, 2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for(var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[func].apply(context, args);
}
次のように呼び出します。
executeFunctionByName("My.Namespace.functionName", window, arguments);
あなたが望むどんなコンテキストでも渡すことができるので、これは上記と同じことになることに注意してください:
executeFunctionByName("Namespace.functionName", My, arguments);
My.Namespace.functionName()
、this
を参照するMy.Namespace
オブジェクト。ただし、を呼び出すと、同じものを参照するexecuteFunctionByName("My.Namespace.functionName", window)
方法はありませんthis
。たぶん、最後の名前空間をスコープとして使用するかwindow
、名前空間がない場合。または、ユーザーが引数としてスコープを指定できるようにすることもできます。
Jason Buntingの非常に便利な機能を少し変更したバージョンを投稿すると思いました。
最初に、slice()に 2番目のパラメーターを指定して、最初のステートメントを簡略化しました。元のバージョンは、IEを除くすべてのブラウザーで正常に動作していました。
次に、これをreturnステートメントのコンテキストに置き換えました。それ以外の場合、これはターゲット関数が実行されているときに常にウィンドウを指していました。
function executeFunctionByName(functionName, context /*, args */) {
var args = Array.prototype.slice.call(arguments, 2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for (var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[func].apply(context, args);
}
この他の質問に対する答えは、その方法を示しています。Pythonのlocals()に相当するJavascriptですか?
基本的に、あなたは言うことができます
window["foo"](arg1, arg2);
または他の多くの人が示唆しているように、あなたはevalを使うだけです:
eval(fname)(arg1, arg2);
何を評価するかについて絶対的に確信がない限り、これは非常に危険です。
これを行うことはできませんか?
var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();
このメソッドを使用して、他のJavaScriptを実行することもできます。
eval("My.Namespace.functionName()");
ですか?
var codeToExecute = "return My.Namespace.functionName()";
エレガントな方法は、ハッシュオブジェクトで関数を定義することだと思います。次に、文字列を使用して、ハッシュからこれらの関数への参照を持つことができます。例えば
var customObject = {
customFunction: function(param){...}
};
その後、呼び出すことができます:
customObject['customFunction'](param);
ここで、customFunctionは、オブジェクトで定義された関数に一致する文字列になります。
ES6を使用すると、クラスメソッドに名前でアクセスできます。
class X {
method1(){
console.log("1");
}
method2(){
this['method1']();
console.log("2");
}
}
let x = new X();
x['method2']();
出力は次のようになります。
1
2
Object.create()
たプロトタイプ委任を使用して、同じ目標を達成できます。const myObj = {method1(){console.log( '1')}、method2(){console.log( '2')}} myObj ['method1'](); // 1 myObj ['method2'](); // 2
すべての回答は、関数がグローバルスコープ(ウィンドウ)からアクセスできることを前提としています。ただし、OPはこの仮定を行いませんでした。
関数がローカルスコープ(別名クロージャ)に存在し、他のローカルオブジェクトによって参照されていない場合は、残念ですeval()
。AFAIK を使用する必要があります。JavaScriptでローカル関数を動的に呼び出すを参照してください
で文字列をポインタに変換するだけですwindow[<method name>]
。例:
var function_name = "string";
function_name = window[function_name];
そして今、あなたはそれをポインタのように使うことができます。
Jason BuntingとAlex Nazarovの優れた回答に対する私の貢献を以下に示します。ここには、Crashalotから要求されたエラーチェックが含まれています。
この(考案された)前文を考えると:
a = function( args ) {
console.log( 'global func passed:' );
for( var i = 0; i < arguments.length; i++ ) {
console.log( '-> ' + arguments[ i ] );
}
};
ns = {};
ns.a = function( args ) {
console.log( 'namespace func passed:' );
for( var i = 0; i < arguments.length; i++ ) {
console.log( '-> ' + arguments[ i ] );
}
};
name = 'nsa';
n_s_a = [ 'Snowden' ];
noSuchAgency = function(){};
次の関数:
function executeFunctionByName( functionName, context /*, args */ ) {
var args, namespaces, func;
if( typeof functionName === 'undefined' ) { throw 'function name not specified'; }
if( typeof eval( functionName ) !== 'function' ) { throw functionName + ' is not a function'; }
if( typeof context !== 'undefined' ) {
if( typeof context === 'object' && context instanceof Array === false ) {
if( typeof context[ functionName ] !== 'function' ) {
throw context + '.' + functionName + ' is not a function';
}
args = Array.prototype.slice.call( arguments, 2 );
} else {
args = Array.prototype.slice.call( arguments, 1 );
context = window;
}
} else {
context = window;
}
namespaces = functionName.split( "." );
func = namespaces.pop();
for( var i = 0; i < namespaces.length; i++ ) {
context = context[ namespaces[ i ] ];
}
return context[ func ].apply( context, args );
}
引数(Arrayオブジェクトを含む)の有無にかかわらず、名前空間またはグローバルの文字列に格納された名前でJavaScript関数を呼び出すことができ、発生したエラー(できればそれらをキャッチ)に関するフィードバックを提供します。
サンプル出力は、それがどのように機能するかを示しています。
// calling a global function without parms
executeFunctionByName( 'a' );
/* OUTPUT:
global func passed:
*/
// calling a global function passing a number (with implicit window context)
executeFunctionByName( 'a', 123 );
/* OUTPUT:
global func passed:
-> 123
*/
// calling a namespaced function without parms
executeFunctionByName( 'ns.a' );
/* OUTPUT:
namespace func passed:
*/
// calling a namespaced function passing a string literal
executeFunctionByName( 'ns.a', 'No Such Agency!' );
/* OUTPUT:
namespace func passed:
-> No Such Agency!
*/
// calling a namespaced function, with explicit context as separate arg, passing a string literal and array
executeFunctionByName( 'a', ns, 'No Such Agency!', [ 007, 'is the man' ] );
/* OUTPUT:
namespace func passed:
-> No Such Agency!
-> 7,is the man
*/
// calling a global function passing a string variable (with implicit window context)
executeFunctionByName( 'a', name );
/* OUTPUT:
global func passed:
-> nsa
*/
// calling a non-existing function via string literal
executeFunctionByName( 'n_s_a' );
/* OUTPUT:
Uncaught n_s_a is not a function
*/
// calling a non-existing function by string variable
executeFunctionByName( n_s_a );
/* OUTPUT:
Uncaught Snowden is not a function
*/
// calling an existing function with the wrong namespace reference
executeFunctionByName( 'a', {} );
/* OUTPUT:
Uncaught [object Object].a is not a function
*/
// calling no function
executeFunctionByName();
/* OUTPUT:
Uncaught function name not specified
*/
// calling by empty string
executeFunctionByName( '' );
/* OUTPUT:
Uncaught is not a function
*/
// calling an existing global function with a namespace reference
executeFunctionByName( 'noSuchAgency', ns );
/* OUTPUT:
Uncaught [object Object].noSuchAgency is not a function
*/
if( typeof context[ functionName ] !== 'function' )
、コンテキスト-ウィンドウ-が定義されており、オブジェクトと配列であるためチェックする行で失敗しますが、ウィンドウ['abcd']は存在しません。回答: window["My.Namespace.functionName"](arguments); // fail
ここに、Es6のアプローチを示します。これにより、文字列としての名前または関数名で関数を呼び出すことができ、さまざまなタイプの関数にさまざまな数の引数を渡すことができます。
function fnCall(fn, ...args)
{
let func = (typeof fn =="string")?window[fn]:fn;
if (typeof func == "function") func(...args);
else throw new Error(`${fn} is Not a function!`);
}
function example1(arg1){console.log(arg1)}
function example2(arg1, arg2){console.log(arg1 + " and " + arg2)}
function example3(){console.log("No arguments!")}
fnCall("example1", "test_1");
fnCall("example2", "test_2", "test3");
fnCall(example3);
fnCall("example4"); // should raise an error in console
setTimeoutの記述がないことに驚いています。
引数なしで関数を実行するには:
var functionWithoutArguments = function(){
console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);
引数を指定して関数を実行するには:
var functionWithArguments = function(arg1, arg2) {
console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");
名前空間の深い関数を実行するには:
var _very = {
_deeply: {
_defined: {
_function: function(num1, num2) {
console.log("Execution _very _deeply _defined _function : ", num1, num2);
}
}
}
}
setTimeout("_very._deeply._defined._function(40,50)", 0);
runMe
いくつかの引数を使用して呼び出す方法の例を追加してください。
だから、他の人が言ったように、間違いなく最良の選択肢は:
window['myfunction'](arguments)
そして、Jason Buntingが言ったように、関数の名前にオブジェクトが含まれている場合は機能しません。
window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work
だから、これは名前ですべての関数を実行する関数の私のバージョンです(オブジェクトを含むかどうかに関係なく):
my = {
code : {
is : {
nice : function(a, b){ alert(a + "," + b); }
}
}
};
guy = function(){ alert('awesome'); }
function executeFunctionByName(str, args)
{
var arr = str.split('.');
var fn = window[ arr[0] ];
for (var i = 1; i < arr.length; i++)
{ fn = fn[ arr[i] ]; }
fn.apply(window, args);
}
executeFunctionByName('my.code.is.nice', ['arg1', 'arg2']);
executeFunctionByName('guy');
let t0 = () => { alert('red0') }
var t1 = () =>{ alert('red1') }
var t2 = () =>{ alert('red2') }
var t3 = () =>{ alert('red3') }
var t4 = () =>{ alert('red4') }
var t5 = () =>{ alert('red5') }
var t6 = () =>{ alert('red6') }
function getSelection(type) {
var evalSelection = {
'title0': t0,
'title1': t1,
'title2': t2,
'title3': t3,
'title4': t4,
'title5': t5,
'title6': t6,
'default': function() {
return 'Default';
}
};
return (evalSelection[type] || evalSelection['default'])();
}
getSelection('title1');
より多くのOOPソリューション...
JasonとAlexの投稿に関するもう1つの詳細。コンテキストにデフォルト値を追加すると便利です。context = context == undefined? window:context;
関数の最初に置くだけです。window
好みのコンテキストに変更することができ、デフォルトのコンテキストでこれを呼び出すたびに同じ変数を渡す必要はありません。
私のコードには非常によく似たものがあります。サードパーティライブラリのコールバックとして渡す必要がある関数名を含むサーバー生成の文字列があります。だから私は文字列を取り、関数への「ポインタ」を返すコードがあり、見つからない場合はnullです。
私の解決策は「Jason Buntingの非常に役立つ機能」*に非常に似ていましたが、自動実行されず、コンテキストは常にウィンドウ上にあります。ただし、これは簡単に変更できます。
うまくいけば、これは誰かに役立つでしょう。
/**
* Converts a string containing a function or object method name to a function pointer.
* @param string func
* @return function
*/
function getFuncFromString(func) {
// if already a function, return
if (typeof func === 'function') return func;
// if string, try to find function or method of object (of "obj.func" format)
if (typeof func === 'string') {
if (!func.length) return null;
var target = window;
var func = func.split('.');
while (func.length) {
var ns = func.shift();
if (typeof target[ns] === 'undefined') return null;
target = target[ns];
}
if (typeof target === 'function') return target;
}
// return null if could not parse
return null;
}
非常に役立つ方法もいくつかあります。
http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx
var arrayMaker = {
someProperty: 'some value here',
make: function (arg1, arg2) {
return [ this, arg1, arg2 ];
},
execute: function_name
};
関数名を含む文字列の一部として渡されている引数の数が不明な場合に役立つ、別のトリックについて言及するのは仕方ありません。例えば:
var annoyingstring = 'call_my_func(123, true, "blah")';
JavaScriptがHTMLページで実行されている場合、必要なのは目に見えないリンクだけです。文字列をonclick
属性に渡し、click
メソッドを呼び出すことができます。
<a href="#" id="link_secret"><!-- invisible --></a>
$('#link_secret').attr('onclick', annoyingstring);
$('#link_secret').click();
または<a>
、実行時に要素を作成します。
複雑な中間関数やevalが必要だったり、ウィンドウのようなグローバル変数に依存しているとは思いません。
function fun1(arg) {
console.log(arg);
}
function fun2(arg) {
console.log(arg);
}
const operations = {
fun1,
fun2
};
let temp = "fun1";
try {
// You have to use square brackets property access
operations["fun1"]("Hello World");
operations["fun2"]("Hello World");
// You can use variables
operations[temp]("Hello World");
} catch (error) {
console.error(error);
}
インポートされた関数でも動作します:
// mode.js
export function fun1(arg) {
console.log(arg);
}
export function fun2(arg) {
console.log(arg);
}
// index.js
import { fun1, fun2 } from "./mod";
const operations = {
fun1,
fun2
};
try {
operations["fun1"]("Hello World");
operations["fun2"]("Hello World");
} catch (error) {
console.error(error);
}
を使用しeval('function()')
ない場合は、を使用して新しい関数を作成できますnew Function(strName)
。以下のコードは、FF、Chrome、IEを使用してテストされました。
<html>
<body>
<button onclick="test()">Try it</button>
</body>
</html>
<script type="text/javascript">
function test() {
try {
var fnName = "myFunction()";
var fn = new Function(fnName);
fn();
} catch (err) {
console.log("error:"+err.message);
}
}
function myFunction() {
console.log('Executing myFunction()');
}
</script>
use this
function executeFunctionByName(functionName, context /*, args */) {
var args = [].slice.call(arguments).splice(2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for(var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[func].apply(context, args);
}
基本的に見て:
var namefunction = 'jspure'; // String
function jspure(msg1 = '', msg2 = '') {
console.log(msg1+(msg2!=''?'/'+msg2:''));
} // multiple argument
// Results ur test
window[namefunction]('hello','hello again'); // something...
eval[namefunction] = 'hello'; // use string or something, but its eval just one argument and not exist multiple
他の型の関数はクラスであり、例はnil petersohnです
非常に役立つ回答をありがとう。私のプロジェクトではJason Buntingの機能を使用しています。
タイムアウトを設定する通常の方法は機能しないため、オプションのタイムアウトを使用するように拡張しました。abhishekisnotさんの質問を参照してください
function executeFunctionByName(functionName, context, timeout /*, args */ ) {
var args = Array.prototype.slice.call(arguments, 3);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for (var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
var timeoutID = setTimeout(
function(){ context[func].apply(context, args)},
timeout
);
return timeoutID;
}
var _very = {
_deeply: {
_defined: {
_function: function(num1, num2) {
console.log("Execution _very _deeply _defined _function : ", num1, num2);
}
}
}
}
console.log('now wait')
executeFunctionByName("_very._deeply._defined._function", window, 2000, 40, 50 );