Use PHP functions in JavaScript

JavaScript call_user_func

Call a user function which is the first parameter

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
22
23
24
2526
27
28
function call_user_func (cb) {
    // Call a user function which is the first parameter  
    // 
    // version: 1008.1718
    // discuss at: http://phpjs.org/functions/call_user_func    // +   original by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Diplom@t (http://difane.com/)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // *     example 1: call_user_func('isNaN', 'a');
    // *     returns 1: true    var func;
 
    if (typeof cb === 'string') {
        func = (typeof this[cb] === 'function') ? this[cb] : func = (new Function(null, 'return ' + cb))();
    } else if (cb instanceof Array) {        func = ( typeof cb[0] == 'string' ) ? eval(cb[0]+"['"+cb[1]+"']") : func = cb[0][cb[1]];
    } else if (typeof cb === 'function') {
        func = cb;
    }
       if (typeof func != 'function') {
        throw new Error(func + ' is not a valid function');
    }
 
    var parameters = Array.prototype.slice.call(arguments, 1);    return (typeof cb[0] === 'string') ? func.apply(eval(cb[0]), parameters) :
                ( typeof cb[0] !== 'object' ) ? func.apply(null, parameters) : func.apply(cb[0], parameters);
}
external links: original PHP docs | raw js source

Examples

Running

1
call_user_func('isNaN', 'a');

Should return

1
true

Dependencies

No dependencies, you can use this function standalone.

Open syntax issues

php.js uses JsLint to help us keep our code consistent and prevent some common bugs.

Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.


Authors

Thanks to the following developers, you get to have call_user_func goodness in JavaScript.

Comments

Add Comment
Use:
[CODE]
your_stuff('here');
[/CODE]
for proper code formatting
By submitting code here you are allowing us to use it in php.js hence dual licensing it under the MIT and GPL licenses

Gravatar
Kevin van Zonneveld
11 Feb '09 Permalink

q  @ Brett Zamir: Yeah sounds good! I will need to do some work on the tester soon. But first the phpjs.org site! The online compiler is coming along nicely have you seen it?

Gravatar
Brett Zamir
6 Feb '09 Permalink

q  I don't know about the errors with Rhino, but maybe that is due to going through window properties?

I concur with your steps of waiting to build a module, and might suggest also waiting for all arguments to be implemented (unless impossible) for any completed functions.

Is it ok for me to move interface_exists() and get_declared_interfaces() (and to add class_implements()) to not porting? JavaScript has no built-in interfaces, so we could not implement these without adding our own language constructs to JavaScript.

Gravatar
Kevin van Zonneveld
1 Feb '09 Permalink

q  @ Brett Zamir: They keep giving me

[CODE="Javascript"]
Exception in thread "Thread-0" org.mozilla.javascript.EcmaError: TypeError: Cannot read property "prototype" from undefined
[/CODE]

..errors, even when I check for prototype first. Rhino issue maybe.

Concidering the functions that are in unported/notporting, etc. That has never been a scientific process. It was the result of a sleepless night of crawling php.net. It has never been more than a rough guideline and has always been open to suggestions.

Bringing me to SPL. I think that may be taking it to another level. That can be a good or a bad thing, but I think for now we should focus on the normal functions & the site of the project. But that's my humble opinion, I'm open to ideas.

btw I think we should move deprecated functions to _notporting, so that's what I did for now.

As far as the Mozilla thing goes. I have actually never made an extension or anything but Yeah it would be cool if we're included at some point. I don't know if they're interested or anything, but no harm in asking, right?
I do think we should further professionalize PHP.JS before taking such steps though.

In my eyes mainly meaning:
- bugfixing
- porting more _unported
- making everything associative-aware
- move out the development process to phpjs.org
- deciding on a good 'default' package that doesn't contain any controversial functions

Gravatar
Brett Zamir
31 Jan '09 Permalink

q  Sorry, also realized the new one I just submitted now for get_class_vars() should have variable names changed to reflect the behavior of this function:
[CODE="Javascript"]
function get_class_vars (name) {
var constructor, retArr={};
if (typeof name === 'function') {
constructor = name;
}
else if (typeof name === 'string') {
constructor = window[name];
}
for (var prop in constructor) {
if (typeof constructor[prop] !== 'function' && prop !== 'prototype') {
retArr[prop] = constructor[prop];
}
}
// Comment out this block to behave as "class" is usually defined in JavaScript convention
for (var prop in constructor.prototype) {
if (typeof constructor.prototype[prop] !== 'function') {
retArr[prop] = constructor.prototype[prop];
}
}
return retArr;
}[/CODE]

Gravatar
Brett Zamir
31 Jan '09 Permalink

q  Sorry, just realized that get_class_method() returns an associative array. Here it is again, along with get_class_vars() and get_object_vars():

[CODE="Javascript"]
function Myclass () {this.privMethod = function(){}}
Myclass.classMethod = function () {}
Myclass.prototype.myfunc1 = function () {
return(true);
};
Myclass.prototype.myfunc2 = function () {
return(true);
}

whatIs(get_class_methods('Myclass'));
var myClassObj = new Myclass();
whatIs(get_class_methods(myClassObj));


function get_class_methods (name) {
var constructor, retArr={};
if (typeof name === 'function') {
constructor = name;
}
else if (typeof name === 'string') {
constructor = window[name];
}
else if (typeof name === 'object') {
constructor = name;
for (var method in constructor.constructor) { // Get class methods of object's constructor
if (typeof constructor.constructor[method] === 'function') {
retArr[method] = constructor.constructor[method];
}
}
// return retArr; // Uncomment to behave as "class" is usually defined in JavaScript convention (and see comment below)
}
for (var method in constructor) {
if (typeof constructor[method] === 'function') {
retArr[method] = constructor[method];
}
}
// Comment out this block to behave as "class" is usually defined in JavaScript convention (and see comment above)
for (var method in constructor.prototype) {
if (typeof constructor.prototype[method] === 'function') {
retArr[method] = constructor.prototype[method];
}
}
return retArr;
}[/CODE]

and:

[CODE="Javascript"]
function Myclass () {this.liveProp = 'prop';}
Myclass.classProp = 'classPropVal';
Myclass.prototype.myprop1 = 1;
Myclass.prototype.myprop2 = 2;

whatIs(get_class_vars('Myclass'));
var myClassObj = new Myclass();
myClassObj.prototype = {a:'b'};


function get_class_vars (name) {
var constructor, retArr={};
if (typeof name === 'function') {
constructor = name;
}
else if (typeof name === 'string') {
constructor = window[name];
}
for (var method in constructor) {
if (typeof constructor[method] !== 'function' && method !== 'prototype') {
retArr[method] = constructor[method];
}
}
// Comment out this block to behave as "class" is usually defined in JavaScript convention
for (var method in constructor.prototype) {
if (typeof constructor.prototype[method] !== 'function') {
retArr[method] = constructor.prototype[method];
}
}
return retArr;
}


function get_object_vars (obj) {
var retArr={};

for (var prop in obj) {
if (typeof obj[prop] !== 'function' && prop !== 'prototype') {
retArr[prop] = obj[prop];
}
}
for (var prop in obj.prototype) {
if (typeof obj.prototype[prop] !== 'function') {
retArr[prop] = obj.prototype[prop];
}
}
return retArr;
}[/CODE]

Gravatar
Brett Zamir
31 Jan '09 Permalink

q  Here's another.... get_class_method(). I've left comments on how to get only the "class methods" as typically used in JavaScript (as opposed to PHP) terminology (i.e., not privileged or prototype methods, but those in the class "namespace").

[CODE="Javascript"]function Myclass () {this.privMethod = function(){}}
Myclass.classMethod = function () {}
Myclass.prototype.myfunc1 = function () {
return(true);
};
Myclass.prototype.myfunc2 = function () {
return(true);
}

alert(get_class_methods('Myclass')); // classMethod,myfunc1,myfunc2
var myClassObj = new Myclass();
alert(get_class_methods(myClassObj));


function get_class_methods (name) {
var constructor, retArr=[];
if (typeof name === 'function') {
constructor = name;
}
else if (typeof name === 'string') {
constructor = window[name];
}
else if (typeof name === 'object') {
constructor = name;
for (var method in constructor.constructor) { // Get class methods of object's constructor
if (typeof constructor.constructor[method] === 'function') {
retArr.push(method);
}
}
// return retArr; // Uncomment to behave as "class" is usually defined in JavaScript convention (and see comment below)
}
for (var method in constructor) {
if (typeof constructor[method] === 'function') {
retArr.push(method);
}
}
// Comment out this block to behave as "class" is usually defined in JavaScript convention (and see comment above)
for (var method in constructor.prototype) {
if (typeof constructor.prototype[method] === 'function') {
retArr.push(method);
}
}
return retArr;
}[/CODE]

Gravatar
Brett Zamir
31 Jan '09 Permalink

q  Also, for get_declared_interfaces() and interface_exists() (and class_implements() but you don't seem to have these in your imported list: http://cn.php.net/manual/en/ref.spl.php -- btw, is it easy to say which modules you included/excluded?), since JavaScript offers no formal way to implement interfaces, do you want to move these to not porting? We could implement our own interface system (which even checked the number of arguments, etc.) and which worked with these PHP-named functions, but I presume that is beyond your intended scope here (though it would be pretty cool to pseudo-standardize on an interface system for JavaScript, at least until JS 2.0).

Off the topic, as far as the php_js global, in the namespaced version of PHP.JS, you could put that at the top of the (function())() closure namespacing, so it wasn't actually global.

And another off-the-topic, https://wiki.mozilla.org/Labs/JS_Modules , they state there "If you would like to contribute a new module, get in touch with us at #labs!", so at whatever point you think we have something, we can submit a PHP-JS module for Mozilla so a bunch of extensions (and the same extension) could be able to reuse the module without any additional loading cost!

Gravatar
Brett Zamir
31 Jan '09 Permalink

q  Hi Kevin,

call_user_method() and call_user_method_array() are now deprecated in PHP in favor of call_user_function (with the array argument). Do you want to move to not porting, or use the following?

[CODE="Javascript"]function call_user_method(method, obj) {
// http://kevin.vanzonneveld.net
// + original by: Brett Zamir

var func = eval(obj+"['"+method+"']");

if (typeof func != 'function') {
throw new Exception(func + ' is not a valid method');
}

return func.apply(null, Array.prototype.slice.call(arguments, 2));
}


function call_user_method_array(method, obj, params) {
// http://kevin.vanzonneveld.net
// + original by: Brett Zamir

var func = eval(obj+"['"+method+"']");

if (typeof func != 'function') {
throw new Exception(func + ' is not a valid method');
}

return func.apply(null, params);
}[/CODE]


Contribute a New function

More functions

In this category

» call_user_func
call_user_func_array
create_function
forward_static_call
forward_static_call_array
func_get_arg
func_get_args
func_num_args
function_exists
get_defined_functions
register_shutdown_function

Support us

spread the word:


Use any PHP function in JavaScript


These kind folks have already donated: @HalfWinter, Paulo Freitas, Andros Peña Romo, Nitin Gupta, @nikosdion, Anonymous, Anonymous and Shawn Houser.
<your name here>

Click here to lend your support to: phpjs and make a donation at www.pledgie.com !