JavaScript var_export
Outputs or returns a string representation of a 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 6061 62 63 64 6566 67 68 69 7071 72 73 74 7576 77 78 79 8081 82 83 84 8586 87 88 89 9091 92 93 94 9596 97 98 99 100101 102 103 104 105106 107 108 109 | function var_export (mixed_expression, bool_return) { // Outputs or returns a string representation of a variable // // version: 1109.2015 // discuss at: http://phpjs.org/functions/var_export // + original by: Philip Peterson // + improved by: johnrembo // + improved by: Brett Zamir (http://brett-zamir.me) // + input by: Brian Tafoya (http://www.premasolutions.com/) // + bugfixed by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Brett Zamir (http://brett-zamir.me) // - depends on: echo // * example 1: var_export(null); // * returns 1: null // * example 2: var_export({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}, true); // * returns 2: "array (\n 0 => 'Kevin',\n 1 => 'van',\n 2 => 'Zonneveld'\n)" // * example 3: data = 'Kevin'; // * example 3: var_export(data, true); // * returns 3: "'Kevin'" var retstr = '', iret = '', cnt = 0, x = [], i = 0, funcParts = [], idtLevel = arguments[2] || 2, // We use the last argument (not part of PHP) to pass in our indentation level innerIndent = '', outerIndent = ''; var getFuncName = function (fn) { var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn); if (!name) { return '(Anonymous)'; } return name[1]; }; var _makeIndent = function (idtLevel) { return (new Array(idtLevel + 1)).join(' '); }; var __getType = function (inp) { var i = 0; var match, type = typeof inp; if (type === 'object' && inp.constructor && getFuncName(inp.constructor) === 'PHPJS_Resource') { return 'resource'; } if (type === 'function') { return 'function'; } if (type === 'object' && !inp) { return 'null'; // Should this be just null? } if (type === "object") { if (!inp.constructor) { return 'object'; } var cons = inp.constructor.toString(); match = cons.match(/(\w+)\(/); if (match) { cons = match[1].toLowerCase(); } var types = ["boolean", "number", "string", "array"]; for (i = 0; i < types.length; i++) { if (cons === types[i]) { type = types[i]; break; } } } return type; }; var type = __getType(mixed_expression); if (type === null) { retstr = "NULL"; } else if (type === 'array' || type === 'object') { outerIndent = _makeIndent(idtLevel - 2); innerIndent = _makeIndent(idtLevel); for (i in mixed_expression) { var value = this.var_export(mixed_expression[i], true, idtLevel + 2); value = typeof value === 'string' ? value.replace(/</g, '<').replace(/>/g, '>') : value; x[cnt++] = innerIndent + i + ' => ' + (__getType(mixed_expression[i]) === 'array' ? '\n' : '') + value; } iret = x.join(',\n'); retstr = outerIndent + "array (\n" + iret + '\n' + outerIndent + ')'; } else if (type === 'function') { funcParts = mixed_expression.toString().match(/function .*?\((.*?)\) \{([\s\S]*)\}/); // For lambda functions, var_export() outputs such as the following: '\000lambda_1' // Since it will probably not be a common use to expect this (unhelpful) form, we'll use another PHP-exportable // construct, create_function() (though dollar signs must be on the variables in JavaScript); if using instead // in JavaScript and you are using the namespaced version, note that create_function() will not be available // as a global retstr = "create_function ('" + funcParts[1] + "', '" + funcParts[2].replace(new RegExp("'", 'g'), "\\'") + "')"; } else if (type === 'resource') { retstr = 'NULL'; // Resources treated as null for var_export } else { retstr = (typeof(mixed_expression) !== 'string') ? mixed_expression : "'" + mixed_expression.replace(/(["'])/g, "\\$1").replace(/\0/g, "\\0") + "'"; } if (bool_return !== true) { this.echo(retstr); return null; } else { return retstr; } } |
Examples
» Example 1
Running
1 | var_export(null); |
Should return
1 | null |
» Example 2
Running
1 | var_export({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}, true); |
Should return
1 | "array (\n 0 => 'Kevin',\n 1 => 'van',\n 2 => 'Zonneveld'\n)" |
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 var_export goodness in JavaScript.
Fixed in SVN. Thanks for the report!
In the meantime, convert "[^]" to "[\s\S]" (no quotes). The former works in PHP and Mozilla JavaScript but not IE--also fixed in the remaining functions which had this problem.
According to IE, there is an error within the regex on line 74...
funcParts = mixed_expression.toString().match(/function .*?\((.*?)\) \{([^]*)\}/);
Claims it is expecting an ']' but I was not able to resolve this.
Hello Tom,
You might look at our serialize implementation http://phpjs.org/functions/view/508 for support for some JS types.
As you might already be aware, you can also get some of this with JSON. See http://json.org if you're not familiar with it or are looking for an existing parser/stringifier (Mozilla provides access to these natively for JSON parsing/stringifying if you were working with Firefox extensions). You technically can just use "eval()" for parsing, but that is unsafe, especially if user input could creep into the expression, unless you know what you're doing with it.
However, it is true that JSON (as with serialize() in some cases) does not allow other JS types, specifically functions (as you list) including as classes, the "undefined" type, Date objects, RegExp objects, and the built-in Error types (see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error ) (unless these are represented in some other way, just as strings or objects), and does not capture the prototype for objects.
That would be a useful option to have, I think, so if someone can implement it, maybe we can have a switch in the function to determine what kind of output to give. For most types, it shouldn't be too hard to do, as you could usually just rely on "toString()" (at least as a base), though you'd have to grab any user-defined prototype object on a function, etc. ...
This is a good example of the cases where being able to have configuration options is useful. php_check_syntax() has a similar dilemma to yours.
We've already built in some support for this which can be used now: PHP-style ini options. So, we could define our own "ini" for this function, using "phpjs." as the "extension prefix" (e.g., "phpjs.var_export_as_js"), and then allow users to use an ini file or ini_set() to set a non-default behavior. The function in turn would do a check like:
// this.php_js.ini would be set earlier, by ini_set(), an ini file
// which directly added to this.php_js.ini (fastest), or by parsing a
// PHP-style ini file (no support for the latter yet).
//
if (this.php_js && this.php_js.ini && this.php_js.ini.local_value['phpjs.var_export_as_js']) { // each ini should define local_value and global_value, so that it is possible to revert within the script back from ini_set() to the default behavior.
...
}
Note that references to 'this' will also work for the non-namespaced version of PHP.JS as it refers to the window object (PHP.JS reserves one global, "php_js", in the non-namespaced version).
At some point in the future, I think Kevin agreed in principle to allowing the namespaced version to accept configuration options in the constructor (e.g., $P = new PHP_JS({phpjs.var_export_as_js:true, ...})), so that, e.g., you could specify that by default you wanted var_export to work with JS.
The returned representation of provided function is valid PHP code (which is correct). But does anyone have a JS var_export function whose returned representation is valid javascript code? The returned value should be string and it could be passed to eval() function
Examples:
var a = new Array(12, '13', 'abc', 'line1\nline2\nline3');
var js_code = var_export(a);
/*
the returned value should be:
"{0:12, 1:'13', 2:'abc', 3:'line1\nline2\nline3'}"
*/
var b = {'key1':4, 'key2':'5', 'key3':'xxx\n123', 555:'text'};
js_code = var_export(b);
/*
the returned value should be:
"{'key1':4, 'key2':'5', 'key3':'xxx\n123', 555:'text'}"
*/
var c = 123;
js_code = var_export(c); // "123"
var d = '321';
js_code = var_export(d); // "'321'"
var e = 'multilne\ntext';
js_code = var_export(e); // "'multiline\ntext'"
function add(x, y)
{
res = x + y;
return res;
}
var js_code = var_export(add);
/*
the returned value should be:
"function add(x, y) { res = x + y; return res; }"
*/
Thanks.
currently this function fails on objects that contain any method. Also, I suggest to use typeof instead of instanceof:
var phpBridge = {
var_export: function (mixed_content) {
var variable=mixed_content;
var __pad_lines = function ( x ) {
return x.split("\n").join("\n ");
};
var retstr = "";
if(typeof variable == ('object' || 'array')) {
var iret = "";
for(i in variable) {
iret=iret+"\n"+this.var_export(i,true)+" => "+this.var_export(variable[i], true)+",";
}
retstr = "array ("+__pad_lines(iret)+"\n)";
} else if( variable === null) {
retstr = "NULL";
} else if ( typeof variable == 'function') {
retstr="'function'";
} else {
retstr = (!isNaN( variable )) ? variable : "'" + variable.replace('/(["\'\])/g', "\\$1").replace('/\0/g', "\\0") + "'";
}
return retstr;
}
}


ekim
20 Apr '11
RA=[]; RA[1]=RA; curse={re:RA}; curse.s=curse;Can the output strings for RA and curse be posted to see what they look like?