Use PHP functions in JavaScript

JavaScript gettype

Returns the type of the variable

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
22
23
24
2526
27
28
29
3031
32
33
34
3536
37
38
39
4041
42
43
44
4546
47
48
49
5051
52
53
54
5556
57
58
59
function gettype (mixed_var) {
    // Returns the type of the variable  
    // 
    // version: 909.322
    // discuss at: http://phpjs.org/functions/gettype    // +   original by: Paulo Ricardo F. Santos
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Douglas Crockford (http://javascript.crockford.com)
    // +   input by: KELAN
    // +   improved by: Brett Zamir (http://brett-zamir.me)    // -    depends on: is_float
    // %        note 1: 1.0 is simplified to 1 before it can be accessed by the function, this makes
    // %        note 1: it different from the PHP implementation. We can't fix this unfortunately.
    // *     example 1: gettype(1);
    // *     returns 1: 'integer'    // *     example 2: gettype(undefined);
    // *     returns 2: 'undefined'
    // *     example 3: gettype({0: 'Kevin van Zonneveld'});
    // *     returns 3: 'array'
    // *     example 4: gettype('foo');    // *     returns 4: 'string'
    // *     example 5: gettype({0: function () {return false;}});
    // *     returns 5: 'array'
    var s = typeof mixed_var, name;
    var getFuncName = function (fn) {        var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn);
        if (!name) {
            return '(Anonymous)';
        }
        return name[1];    };
    if (s === 'object') {
        if (mixed_var !== null) { // From: http://javascript.crockford.com/remedial.html
            if (typeof mixed_var.length === 'number' &&
                    !(mixed_var.propertyIsEnumerable('length')) &&                    typeof mixed_var.splice === 'function') {
                s = 'array';
            }
            else if (mixed_var.constructor && getFuncName(mixed_var.constructor)) {
                name = getFuncName(mixed_var.constructor);                if (name === 'Date') {
                    s = 'date'; // not in PHP
                }
                else if (name === 'RegExp') {
                    s = 'regexp'; // not in PHP                }
                else if (name === 'PHPJS_Resource') { // Check against our own resource constructor
                    s = 'resource';
                }
            }        } else {
            s = 'null';
        }
    }
    else if (s === 'number') {        s = this.is_float(mixed_var) ? 'double' : 'integer';
    }
    return s;
}
external links: original PHP docs | raw js source

Examples

» Example 1

Running

1
gettype(1);

Should return

1
'integer'

» Example 2

Running

1
gettype(undefined);

Should return

1
'undefined'

Dependencies

In order to use this function, you also need:

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 gettype 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
Brett Zamir
30 Apr '09 Permalink

q  @KELAN, While it is a nice try and would probably work in most cases, I agree with Kevin that we should avoid relying on the default toString() implementation. See the discussion for is_array() for possible solutions to the perennial challenge with arrays. :) However, I do agree with your desire to allow testing for Date, RegExp and along with simplifying our implementation I've added support for these and also our own resource type: http://trac.phpjs.org/projects/phpjs/browser/trunk/functions/var/gettype.js Thanks!

Gravatar
Kevin van Zonneveld
29 Apr '09 Permalink

q  @ KELAN: I noticed your version relies on toString. This raises a question for me. What if people supply objects that actually return some custom string?

Gravatar
KELAN
28 Apr '09 Permalink

q  

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
function gettype(mixed_var){
        switch (Object.prototype.toString.apply(mixed_var)){
                case '[object Array]'   : return 'array';
                case '[object Function]': return 'function';
                case '[object String]'  : return 'string';                case '[object RegExp]'  : return 'regexp';
                case '[object Boolean]' : return 'boolean';
                case '[object Date]'    : return 'date';
                case '[object Math]'    : return 'math';
                case '[object Number]'  : {                        if (parseFloat(mixed_var) != parseInt(mixed_var)) return 'double';
                        else return 'integer';
                }
                case '[object Object]'  : {
                        if(mixed_var===undefined)return 'undefined';                        else if(mixed_var==null)return 'NULL';
                        else return 'object';
                }
                default : return 'unknown type';
        }}

Gravatar
Brett Zamir
28 Jan '09 Permalink

q   Yes, this function won't work unless you pass the variable as a string (and then only if the variable is in a global context). There's no other way to change the type of the variable by reference like that, so that was the only way we can mimic the PHP behavior here.

1
2
3
4
56
$foo = "5bar"; // string
$bar = true;   // boolean
settype('$foo', "integer"); // $foo is now 5   (integer)
alert(typeof $foo); // number
settype('$bar', "string");  // $bar is now "1" (string)alert(typeof $bar); // string

Gravatar
Kevin van Zonneveld
26 Jan '09 Permalink

q  @ Brett Zamir & Onno Marsman: Can't submit yet, but actually made some progress with the UI today:
http://phpjs.org/packages/configure

You can play around with the get_html_translation_table, html_entity_decode, htmlentities, htmlspecialchars, htmlspecialchars_decode a bit to get the idea.

I personally would like to focus my time a bit more towards the site for now. Brett, is it an idea we get you SVN access? We don't always agree on implementations but I'm sure by now you have a solid understanding beforehand of what functions are controversial in the eyes of Onno & myself. We could always talk about it then.

This way you can directly patch/add your functions, and I can use my IDE primarily for phpjs.org for the time being. If not: no problem at all, Just let me know ok? Might as well pimp you to core member if you're interested (in fact there's no real difference, just the name) :)

Gravatar
Kevin van Zonneveld
25 Jan '09 Permalink

q   @ Brett Zamir: For some reason when it reaches case 'integer', I can't set the this[vr] to anything anymore. Strange, because the other (var bar) example does work.

And by the way, I believe congratulations are in order Brett:
http://phpjs.org/authors/index :)

I'm going to do some work on the site now, Pedro Sland has supplied a jquery component to the compiler I'm anxious to wire up.

Gravatar
Kevin van Zonneveld
25 Jan '09 Permalink

q  @ Brett Zamir: Processed everything: still having a bit of a problem with the first testcase. It continues to return 5bar but I will look into it.

Gravatar
Brett Zamir
24 Jan '09 Permalink

q   The regular expression line under 'float' should be changed to this:

var mtch = v.match(/^([+-]?)(\d+(\.\d+)?|\.\d+)([eE][+-]?\d+)?/);

(Had forgotten the +/- after exponent...)

Gravatar
Brett Zamir
24 Jan '09 Permalink

q  Sorry, I see you already have is_double(), but you CAN add is_real() as an alias of is_float()...

Gravatar
Brett Zamir
24 Jan '09 Permalink

q  By the way, you can get doubleval() by returning floatval() on it, and get is_double() by returning is_float().

I think you should change get_resource_type() and is_resource() to not porting (unless you just want to return false for the latter!), since JavaScript doesn't have the resource type.

Gravatar
Brett Zamir
24 Jan '09 Permalink

q  Missing a semicolon with return in is_array...

Gravatar
Brett Zamir
24 Jan '09 Permalink

q   Here's settype() following PHP behavior

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
22
23
24
2526
27
28
29
3031
32
33
34
3536
37
38
39
4041
42
43
44
4546
47
48
49
5051
52
53
54
5556
57
58
59
6061
62
63
64
6566
67
68
69
7071
72
73
74
7576
77
78
79
80
// Credits to Crockford also
// only works on global variables, and "vr" must be passed in as a string
function settype (vr, type) {
    function is_array(arr) {
        return typeof arr === 'object' && typeof arr.length === 'number' &&                    !(arr.propertyIsEnumerable('length')) &&
                    typeof arr.splice === 'function'
    }
    v = this[vr];
    try {        switch(type) {
            case 'boolean':
                if (is_array(v) && v.length === 0) {this[vr]=false;}
                else if (v === '0') {this[vr]=false;}
                else if (typeof v === 'object' && !is_array(v)) {                    var lgth = false;
                    for (var i in v) {
                        lgth = true;
                    }
                    this[vr]=lgth;                }
                else {this[vr] = !!v;}
                break;
            case 'integer':
                if (typeof v === 'number') {this[vr]=parseInt(v, 10);}                else if (typeof v === 'string') {
                    var mtch = v.match(/^([+-]?)(\d+)/);
                    if (!mtch) {this[vr]=0;}
                    else {this[vr]=parseInt(v, 10);}
                }                else if (v === true) {this[vr]=1;}
                else if (v === false || v === null) {this[vr]=0;}
                else if (is_array(v) && v.length === 0) {this[vr]=0;}
                else if (typeof v === 'object') {this[vr]=1;}
                break;            case 'float':
                if (typeof v === 'string') {
                    var mtch = v.match(/^([+-]?)(\d+(\.\d+)?|\.\d+)([eE]\d+)?/);
                    if (!mtch) {this[vr]=0;}
                    else {this[vr]=parseFloat(v, 10);}                }
                else if (v === true) {this[vr]=1;}
                else if (v === false || v === null) {this[vr]=0;}
                else if (is_array(v) && v.length === 0) {this[vr]=0;}
                else if (typeof v === 'object') {this[vr]=1;}                break;
            case 'string':
                if (v === null || v === false) {this[vr]='';}
                else if (is_array(v)) {this[vr]='Array';}
                else if (typeof v === 'object') {this[vr]='Object';}                else if (v === true) {this[vr]='1';}
                else {this[vr] += '';} // numbers (and functions?)
                break;
            case 'array':
                if (v === null) {this[vr] = [];}                else if (typeof v !== 'object') {this[vr] = [v];}
                break;
            case 'object':
                if (v === null) {this[vr]={};}
                else if (is_array(v)) {                    for (var i=0, obj={}; i < v.length; i++) {
                        obj[i] = v;
                    }
                    this[vr] = obj;
                }                else if (typeof v !== 'object') {this[vr]={scalar:v};}
                break;
            case 'null':
                delete this[vr];
                break;        }
        return true;
    }
    catch (e) {
        return false;    }
} 
var a =5;
settype('a', 'object');
alert(typeof a);

Gravatar
Onno Marsman
15 Jan '09 Permalink

q  Unless you really want to check the javascript type. I guess functions that check for the type array really do this to make a distinction between associative array like objects and real javascript arrays. So I don't really think there is a problem...

Gravatar
Kevin van Zonneveld
14 Jan '09 Permalink

q  @ Onno Marsman: Yes but since this was such a controversial issue, I really do like to have that check in place.

Just like we now wish that we had implemented is_array in every function before so that we get only one point of control we need to update when a decision is made.

Gravatar
Onno Marsman
13 Jan '09 Permalink

q  Because of the way is_array is implemented this function will never return 'object'. The call to is_object is now useless.


Contribute a New function