Kie*_*ron 994 javascript
我在JavaScript中将函数的名称作为字符串.如何将其转换为函数指针,以便稍后调用?
根据具体情况,我可能还需要将各种参数传递给方法.
一些功能可能采取的形式namespace.namespace.function(args[...]).
Jas*_*ing 1382
不要使用,eval除非你绝对,没有其他选择.
如前所述,使用这样的东西是最好的方法:
window["functionName"](arguments);
Run Code Online (Sandbox Code Playgroud)
但是,这不适用于命名空间函数:
window["My.Namespace.functionName"](arguments); // fail
Run Code Online (Sandbox Code Playgroud)
这是你怎么做的:
window["My"]["Namespace"]["functionName"](arguments); // succeeds
Run Code Online (Sandbox Code Playgroud)
为了使这更容易并提供一些灵活性,这里有一个方便的功能:
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);
}
Run Code Online (Sandbox Code Playgroud)
你会这样称呼它:
executeFunctionByName("My.Namespace.functionName", window, arguments);
Run Code Online (Sandbox Code Playgroud)
注意,你可以传入你想要的任何上下文,所以这将与上面相同:
executeFunctionByName("Namespace.functionName", My, arguments);
Run Code Online (Sandbox Code Playgroud)
小智 98
只是觉得我发布了一个略有改动版的Jason Bunting非常有用的功能.
首先,我通过向slice()提供第二个参数来简化第一个语句.原始版本在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);
}
Run Code Online (Sandbox Code Playgroud)
Eli*_*ght 60
这个问题的答案告诉你如何做到这一点:Javascript相当于Python的本地人()?
基本上,你可以说
window["foo"](arg1, arg2);
Run Code Online (Sandbox Code Playgroud)
或许多其他人建议,你可以使用eval:
eval(fname)(arg1, arg2);
Run Code Online (Sandbox Code Playgroud)
虽然这是非常不安全的,除非你完全确定你正在评估什么.
小智 50
你能不能这样做:
var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();
Run Code Online (Sandbox Code Playgroud)
您还可以使用此方法执行任何其他JavaScript.
Rub*_*rio 43
我认为这样做的一种优雅方式是在哈希对象中定义函数.然后,您可以使用字符串从哈希中引用这些函数.例如
var customObject = {
customFunction: function(param){...}
};
Run Code Online (Sandbox Code Playgroud)
然后你可以打电话:
customObject['customFunction'](param);
Run Code Online (Sandbox Code Playgroud)
其中customFunction将是与对象中定义的函数匹配的字符串.
nil*_*ohn 28
使用ES6,您可以按名称访问类方法:
class X {
method1(){
console.log("1");
}
method2(){
this['method1']();
console.log("2");
}
}
let x = new X();
x['method2']();
Run Code Online (Sandbox Code Playgroud)
输出将是:
1
2
Run Code Online (Sandbox Code Playgroud)
ann*_*ata 23
两件事情:
避免评估,它非常危险和缓慢
其次,你的功能存在于哪里并不重要,"全球" - 无关紧要.x.y.foo()可通过启用x.y['foo']()或x['y']['foo']()甚至window['x']['y']['foo']().你可以像这样无限期地链接.
Wol*_*ehn 15
所有答案都假设可以通过全局范围(aka窗口)访问这些函数.然而,OP没有做出这个假设.
如果函数存在于本地范围(也就是闭包)并且没有被其他一些本地对象引用,那么运气不好:你必须使用eval() AFAIK,看看 在javascript中动态调用本地函数
小智 13
您只需要将字符串转换为指针window[<method name>].例:
var function_name = "string";
function_name = window[function_name];
Run Code Online (Sandbox Code Playgroud)
现在你可以像指针一样使用它.
Mac*_*Mac 11
以下是我对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(){};
Run Code Online (Sandbox Code Playgroud)
然后是以下功能:
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 );
}
Run Code Online (Sandbox Code Playgroud)
将允许您通过存储在字符串中的名称调用javascript函数,无论是命名空间还是全局,带或不带参数(包括Array对象),提供有关遇到的任何错误的反馈(希望能够捕获它们).
示例输出显示了它的工作原理:
// 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
*/
Run Code Online (Sandbox Code Playgroud)
如果要调用对象的函数而不是全局函数window["functionName"].你可以这样做;
var myObject=new Object();
myObject["functionName"](arguments);
Run Code Online (Sandbox Code Playgroud)
例:
var now=new Date();
now["getFullYear"]()
Run Code Online (Sandbox Code Playgroud)
根据您所在的位置,您还可以使用:
this["funcname"]();
self["funcname"]();
window["funcname"]();
top["funcname"]();
globalThis["funcname"]();
Run Code Online (Sandbox Code Playgroud)
或者,在nodejs中
global["funcname"]()
Run Code Online (Sandbox Code Playgroud)
小心!!!
应该尽量避免在JavaScript中通过字符串调用函数,原因有两个:
原因1:某些代码混淆器会破坏您的代码,因为它们会更改函数名称,使字符串无效.
原因2:维护使用此方法的代码要困难得多,因为找到字符串调用的方法的用法要困难得多.
这是我的Es6方法,它使您可以通过名称作为字符串或函数名称来调用函数,还可以将不同数量的参数传递给不同类型的函数:
function fnCall(fn, ...args)
{
let func = (typeof fn =="string")?window[fn]:fn;
if (typeof func == "function") func(...args)
else console.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 consoleRun Code Online (Sandbox Code Playgroud)
很惊讶没有提到setTimeout.
要运行不带参数的函数:
var functionWithoutArguments = function(){
console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);
Run Code Online (Sandbox Code Playgroud)
要使用参数运行函数:
var functionWithArguments = function(arg1, arg2) {
console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");
Run Code Online (Sandbox Code Playgroud)
要运行深度命名空间的函数:
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);
Run Code Online (Sandbox Code Playgroud)
I don't think you need complicated intermediate functions or eval or be dependent on global variables like window:
function fun1(arg) {
console.log(arg);
}
function fun2(arg) {
console.log(arg);
}
const operations = {
fun1,
fun2
};
operations["fun1"]("Hello World");
operations.fun2("Hello World");
// You can use intermediate variables, if you like
let temp = "fun1";
operations[temp]("Hello World");
Run Code Online (Sandbox Code Playgroud)
It will also work with imported functions:
// mode.js
export function fun1(arg) {
console.log(arg);
}
export function fun2(arg) {
console.log(arg);
}
Run Code Online (Sandbox Code Playgroud)
// index.js
import { fun1, fun2 } from "./mod";
const operations = {
fun1,
fun2
};
operations["fun1"]("Hello World");
operations["fun2"]("Hello World");
Run Code Online (Sandbox Code Playgroud)
Since it is using property access, it will survive minimization or obfuscation, contrary to some answers you will find here.
| 归档时间: |
|
| 查看次数: |
490477 次 |
| 最近记录: |