当名称为字符串时,如何执行JavaScript函数
我将JavaScript中的函数名作为字符串。如何将其转换为函数指针,以便稍后调用 根据具体情况,我可能还需要将各种参数传递给该方法当名称为字符串时,如何执行JavaScript函数,javascript,Javascript,我将JavaScript中的函数名作为字符串。如何将其转换为函数指针,以便稍后调用 根据具体情况,我可能还需要将各种参数传递给该方法 有些函数可能采用名称空间.namespace.function(args[…])对另一个问题的回答向您展示了如何做到这一点: 基本上,你可以说 window["foo"](arg1, arg2); 或者正如许多其他人所建议的,您可以使用eval: eval(fname)(arg1, arg2); 尽管这是非常不安全的,除非你完全确定你在评估什么。两件事: 避
有些函数可能采用
名称空间.namespace.function(args[…])
对另一个问题的回答向您展示了如何做到这一点:
基本上,你可以说
window["foo"](arg1, arg2);
或者正如许多其他人所建议的,您可以使用eval:
eval(fname)(arg1, arg2);
尽管这是非常不安全的,除非你完全确定你在评估什么。两件事:
- 避免评估,这是非常危险和缓慢的
- 其次,你的功能存在于何处并不重要,“全局性”是不相关的
可以通过x.y.foo()
或x.y['foo']()
甚至x['y']['foo']()
window['x']['y']['foo']()启用。你可以像这样无限期地连锁
eval
,除非你绝对没有其他选择
如前所述,使用这样的方法是最好的:
window["functionName"](arguments);
但是,这不适用于命名空间的函数:
window["My.Namespace.functionName"](arguments); // fail
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);
}
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);
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 );
}
这是您将如何做到的:
window["My"]["Namespace"]["functionName"](arguments); // succeeds
为了简化操作并提供一定的灵活性,这里提供了一个方便的功能:
window["My.Namespace.functionName"](arguments); // fail
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);
}
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);
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 );
}
注意,您可以在任何上下文中传递,因此这与上面的操作相同:
executeFunctionByName("Namespace.functionName", My, arguments);
我只是想发布一个稍微修改过的版本 首先,我通过向slice()提供第二个参数简化了第一条语句。原始版本在除IE之外的所有浏览器中都运行良好 第二,我在return语句中将其替换为context;否则,在执行目标函数时,它总是指向窗口
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);
}
function executeFunctionByName(functionName,context/*,args*/){
var args=Array.prototype.slice.call(参数,2);
var namespace=functionName.split(“.”);
var func=namespaces.pop();
for(var i=0;i
您只需通过窗口[]
将字符串转换为指针即可。
例如:
现在你可以像指针一样使用它。还有一些非常有用的方法
关于Jason和Alex帖子的更多细节。我发现在上下文中添加默认值很有帮助。只需放置
context=context==未定义?窗口:上下文代码>在函数的开头。您可以将window
更改为您首选的上下文,这样您就不必每次在默认上下文中调用时都传入相同的变量。如果您想使用window[“functionName”]
调用对象的函数而不是全局函数。你可以这样做
var myObject=new Object();
myObject["functionName"](arguments);
例如:
var now=new Date();
now["getFullYear"]()
你能不能不这样做:
var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();
您还可以使用此方法执行任何其他JavaScript。所有答案都假定可以通过全局范围(窗口)访问函数。然而,OP没有做出这一假设
如果函数位于局部作用域(也称为闭包)中,并且没有被其他局部对象引用,则会带来厄运:您必须使用eval()
AFAIK,请参阅
为了补充Jason Bunting的答案,如果您使用的是nodejs或其他东西(这在dom js中也适用),您可以使用这个而不是窗口(请记住:eval是邪恶的:
this['fun'+'ctionName']();
小心!!!
出于两个原因,应尽量避免在JavaScript中通过字符串调用函数:
原因1:一些代码混淆器会破坏代码,因为它们会更改函数名,使字符串无效
原因2:维护使用这种方法的代码要困难得多,因为查找字符串调用的方法的用法要困难得多。惊讶地发现没有提到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 functionWithoutArguments = function(){
console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);
var functionWithArguments = function(arg1, arg2) {
console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");
要运行深度命名空间函数,请执行以下操作:
window["My.Namespace.functionName"](arguments); // fail
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);
}
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);
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 );
}
我的代码中有一个非常相似的东西。
我有一个服务器生成的字符串,其中包含一个函数名,我需要将该函数名作为回调传递给第三方库。因此,我有一个代码获取该字符串并返回指向该函数的“指针”,如果找不到,则返回null
我的解决方案非常类似于“”,虽然它不会自动执行,并且上下文总是在窗口上。但是这很容易修改
希望这将有助于某人
/**
* 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;
}
因此,正如其他人所说,最好的选择无疑是:
window['myfunction'](arguments)
而且,如果函数的名称包含对象,则它将不起作用:
window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work
下面是我的函数版本,它将按名称执行所有函数(包括对象或不包括对象):
my={
代码:{
是:{
nice:函数(a,b){alert(a+,“+b);}
}
}
};
guy=函数(){alert('awesome');}
函数executeFunctionByName(str,args)
{
var arr=str.split('.');
var fn=窗口[arr[0]];
对于(变量i=1;i executeFunctionByName('guy');
我认为一种优雅的方法是在散列对象中定义函数。然后可以使用字符串从散列中引用这些函数
var customObject = {
customFunction: function(param){...}
};
然后你可以打电话:
customObject['customFunction'](param);
其中customFunction是与对象中定义的函数匹配的字符串
更新
这个答案似乎对很多其他的程序员都有帮助,所以这里有一个更新版本
使用ES6,您还可以使用计算属性名,这将允许您避免使用魔术字符串
const FunctionNames=Object.freeze({
Fi
function testfunc(){
return "hello world";
}
$( document ).ready(function() {
$("div").html(eval("testfunc"));
});
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 );
}
// 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
*/
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');
/*
Author: Hugo Reyes
@ www.teamsrunner.com
*/
(function ( W, D) { // enclose it as self invoking function to avoid name collisions.
// to call function1 as string
// initialize your FunctionHUB as your namespace - context
// you can use W["functionX"](), if you want to call a function at the window scope.
var container = new FunctionHUB();
// call a function1 by name with one parameter.
container["function1"](' Hugo ');
// call a function2 by name.
container["function2"](' Hugo Leon');
// OO style class
function FunctionHUB() {
this.function1 = function (name) {
console.log('Hi ' + name + ' inside function 1')
}
this.function2 = function (name) {
console.log('Hi' + name + ' inside function 2 ')
}
}
})(window, document); // in case you need window context inside your namespace.
this["funcname"]();
self["funcname"]();
window["funcname"]();
top["funcname"]();
globalThis["funcname"]();
global["funcname"]()