最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript equivalent of php call_user_func - Stack Overflow

programmeradmin0浏览0评论

I've found this topic which I've implemented (see accepted answer):
javascript equivalent of PHP's call_user_func()

However, I am having a problem with multiple parameters. I realize what I was doing was turning my parameters into strings and treating it like 1 parameter, but I don't know how to fix this because I am dynamically creating the parameters.

Meaning, I have defined in my code the following:

var a = new Array();
a[0] = new Array();
a[0][0] = 'alert';
a[0][1] = '\'Hello World\'';
a[1] = new Array();
a[1][0] = 'setTimeout';
a[1][1] = 'alert("goodbye world")';
a[1][2] = '20';

Later, I was calling them like this:

    var j = 0;
    var len = 0;
    var fx = '';
    var params = '';
    for( i in a ){
        params = '';
        len = a[i].length;
        fx = a[i][0]; // getting the function name
        a[i].splice( 0, 1 ); // removing it from array
        if( len > 1 ){
            params = a[i].join(", "); // trying to turn the parameters into the right format, but this is turning it into strings I think
            params = params.replace(/\\'/g,'\''); // bc i was adding slashes with PHP
        }
        window[fx](params);
    }

I don't have to use arrays to do this. I don't understand JS OOP (haven't tried yet), though I am comfortable with PHP OOP, so I don't know if there is a way to do this there.

Any help on passing multiple parameters would be appreciated.

Thanks.

I've found this topic which I've implemented (see accepted answer):
javascript equivalent of PHP's call_user_func()

However, I am having a problem with multiple parameters. I realize what I was doing was turning my parameters into strings and treating it like 1 parameter, but I don't know how to fix this because I am dynamically creating the parameters.

Meaning, I have defined in my code the following:

var a = new Array();
a[0] = new Array();
a[0][0] = 'alert';
a[0][1] = '\'Hello World\'';
a[1] = new Array();
a[1][0] = 'setTimeout';
a[1][1] = 'alert("goodbye world")';
a[1][2] = '20';

Later, I was calling them like this:

    var j = 0;
    var len = 0;
    var fx = '';
    var params = '';
    for( i in a ){
        params = '';
        len = a[i].length;
        fx = a[i][0]; // getting the function name
        a[i].splice( 0, 1 ); // removing it from array
        if( len > 1 ){
            params = a[i].join(", "); // trying to turn the parameters into the right format, but this is turning it into strings I think
            params = params.replace(/\\'/g,'\''); // bc i was adding slashes with PHP
        }
        window[fx](params);
    }

I don't have to use arrays to do this. I don't understand JS OOP (haven't tried yet), though I am comfortable with PHP OOP, so I don't know if there is a way to do this there.

Any help on passing multiple parameters would be appreciated.

Thanks.

Share Improve this question edited May 23, 2017 at 12:33 CommunityBot 11 silver badge asked Apr 8, 2012 at 8:12 phpmehphpmeh 1,7922 gold badges23 silver badges44 bronze badges 11
  • 1 window[fx].apply(obj, params) – Cheeso Commented Apr 8, 2012 at 8:19
  • 2 You are shooting yourself in the foot here. For starters: You should not have an array that contains code as strings, this is just wrong. And don't get me started on interpreting these strings with regex. What are you trying to do? Further: Never use a for .. in loop on an array, and you should not use new Array() at all. – Tomalak Commented Apr 8, 2012 at 8:42
  • @Tomalak Sorry but that advice is unsound. JSONP for examples and server-defined callbacks will have functions as strings. It is safer to check and call a function by string name than to run an eval. Personally I agree about Regex, but technically it is perfectly viable for the task. Use for .. in when appropriate, which is often. Using new Array() when you want to create your own containers prototypes is quite handy. – That Realty Programmer Guy Commented Sep 12, 2021 at 3:13
  • 1 @GaretClaborn No offense, but I'm really tired this debate, and this thread is almost 10 years old. Your "eval isn't all bad" and "using regex on code makes eval safer" is also nothing but a highly opinionated position. Every piece of programming advice is. Every "rule" is just a convention, usually from people with more experience who found that doing or avoiding certain things is beneficial. Discouraging beginners from writing eval-based solutions when there are other options available is a perfectly reasonable point of view, and I've stated the reasons for that. You're welcome to disagree. – Tomalak Commented Sep 13, 2021 at 9:52
  • 1 Going back to my code 9 years ago is pretty cringy even for me. – phpmeh Commented Sep 13, 2021 at 15:40
 |  Show 6 more comments

3 Answers 3

Reset to default 15

First thing to do: Scrap your entire code, start over. Your approach will not get you anywhere where you'd want to be. (Unfortunately I can't tell you where you'd want to be because I cannot make sense of your example.)

There are three ways to call a function in JavaScript.

function foo() { console.log(arguments); }

// 1. directly
foo(1, 2, 3);

// 2. trough Function.call()
foo.call(this, 1, 2, 3);

// 3. trough Function.apply()
var args = [1, 2, 3];
foo.apply(this, args);

call and apply are similar. They let you decide which object the this keyword will point to inside the function (that's the important bit!).

apply accepts an array of arguments, call accepts individual arguments.

The closest thing to call() is PHP's call_user_func(). The closest thing to apply() is PHP's call_user_func_array().

JavaScript objects share something with PHP arrays: They are key/value pairs.

// an anonymous function assigned to the key "foo"
var obj = {
  foo: function () { console.log(arguments); }
};

This means you can access object properties either with the dot notation:

// direct function call
obj.foo(1, 2, 3);

Or through square bracket notation (note that object keys are strings):

var funcName = "foo";
obj[funcName](1, 2, 3);
obj[funcName].call(obj, 1, 2, 3);
obj[funcName].apply(obj, [1, 2, 3]);

Square bracket notation gives you the freedom to choose an object property dynamically. If this property happens to be a function, apply() gives you the freedom to choose function arguments dynamically.

Every top-level function that has not been declared as the property of some object will become the property of the global object. In browsers the global object is window. (So the function foo() in my first code block above really is window.foo.)

Note that this does not work like in PHP. It will point to the object the function has been called on, not the object the function "belongs to". (The concept "belongs to" does not really exist in JavaScript. Things can be modeled that way, but it's only a convention.)

With direct calling (obj.foo(1, 2, 3)), this will point to obj. With call and apply, this will point to whatever object you want to. This is a lot more useful than it sounds at first. Most of the time when you want to call functions dynamically, you will end up using apply.

Check out Function.apply:

function test(a, b) { console.log([a, b]) }

test.apply(null, [1, 2]); // => [ 1, 2 ]

Late to the party, but now with ES6 you can simply do

function FunctionX(a,b,c,d){
    return a + b + c + d;
}

let fx = "FunctionX";
let params = [ 1, 10, 100, 200 ];

let answer = window[fx]( ... params);
let answer2 = globalThis[fx]( ... params );   // this is more cross-platform

to unpack your argument array

发布评论

评论列表(0)

  1. 暂无评论