我有一个JavaScript函数的名称作为字符串。如何将其转换为函数指针以便稍后调用?
根据具体情况,我可能还需要将各种参数传递到方法中。
一些函数可以采用namespace.namespace.function(args[…])的形式。
我有一个JavaScript函数的名称作为字符串。如何将其转换为函数指针以便稍后调用?
根据具体情况,我可能还需要将各种参数传递到方法中。
一些函数可以采用namespace.namespace.function(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
存在其他类型的函数类,看例子
其他回答
以下是我对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 );
}
将允许您通过存储在字符串中的名称(命名空间或全局)调用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
*/
我只是想发布一个稍微改变了的Jason Bunting非常有用的函数。
首先,我通过向slice()提供第二个参数简化了第一个语句。最初的版本在除IE之外的所有浏览器中都运行良好。
其次,我在return语句中用context替换了它;否则,在执行目标函数时,它总是指向window。
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);
}
不使用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>
我认为你不需要复杂的中间函数或eval,也不需要依赖像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");
它也可以使用导入的函数:
// 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
};
operations["fun1"]("Hello World");
operations["fun2"]("Hello World");
因为它使用的是属性访问,所以它将在最小化或混淆中存活下来,这与您在这里找到的一些答案相反。
你可以把你的函数名放在一个Array对象中,然后调用每个函数对应的数组键来执行它,DEMO:
function captchaTest(msg){
let x = Math.floor(Math.random()*(21-1)) +1;
let y = Math.floor(Math.random()*(11-1)) +1;
let sum = function(){
return x+y;
}
let sub = function(){
if (y > x){
let m = y;
y = x;
x = m;
console.log(x,y,m,'--')
}
return x-y;
}
let mul = function(){
return x*y;
}
let OParr = [sum(), sub(), mul()];
let OP = Math.floor(Math.random()*OParr.length);
let s = OParr[OP]; //!!! HERE !!! is the call as array element
switch(OP){
case 0:
opra = '+';
break;
case 1:
opra = '━';
break;
default:
opra = '✖';
}
let msg2 = 'Answer the following question to continue:'
let p = prompt(msg+' '+msg2+'\n'+'What is the result of '+x+opra+y+' ?','')
console.log(s,p,OP)
if (s == p){
alert ('Wow, Correct Answer!')
return true;
}
else{
alert('Sorry, the answer is not correct!')
return false;
}
}