PHP's var_dump in JavaScript

Here’s what our current JavaScript equivalent to PHP's var_dump looks like.

module.exports = functionvar_dump () { // eslint-disable-line camelcase
// discuss at: https://locutus.io/php/var_dump/
// original by: Brett Zamir (https://brett-zamir.me)
// improved by: Zahlii
// improved by: Brett Zamir (https://brett-zamir.me)
// note 1: For returning a string, use var_export() with the second argument set to true
// test: skip-all
// example 1: var_dump(1)
// returns 1: 'int(1)'
const echo = require('../strings/echo')
let output = ''
const padChar = ' '
const padVal = 4
let lgth = 0
let i = 0
const _getFuncName = function (fn) {
const name = (/\W*function\s+([\w$]+)\s*\(/)
.exec(fn)
if (!name) {
return'(Anonymous)'
}
return name[1]
}
const _repeatChar = function (len, padChar) {
let str = ''
for (let i = 0; i < len; i++) {
str += padChar
}
return str
}
const _getInnerVal = function (val, thickPad) {
let ret = ''
if (val === null) {
ret = 'NULL'
} elseif (typeof val === 'boolean') {
ret = 'bool(' + val + ')'
} elseif (typeof val === 'string') {
ret = 'string(' + val.length + ') "' + val + '"'
} elseif (typeof val === 'number') {
if (parseFloat(val) === parseInt(val, 10)) {
ret = 'int(' + val + ')'
} else {
ret = 'float(' + val + ')'
}
} elseif (typeof val === 'undefined') {
// The remaining are not PHP behavior because these values
// only exist in this exact form in JavaScript
ret = 'undefined'
} elseif (typeof val === 'function') {
const funcLines = val.toString()
.split('\n')
ret = ''
for (let i = 0, fll = funcLines.length; i < fll; i++) {
ret += (i !== 0 ? '\n' + thickPad : '') + funcLines[i]
}
} elseif (val instanceofDate) {
ret = 'Date(' + val + ')'
} elseif (val instanceofRegExp) {
ret = 'RegExp(' + val + ')'
} elseif (val.nodeName) {
// Different than PHP's DOMElement
switch (val.nodeType) {
case1:
if (typeof val.namespaceURI === 'undefined' ||
val.namespaceURI === 'https://www.w3.org/1999/xhtml') {
// Undefined namespace could be plain XML, but namespaceURI not widely supported
ret = 'HTMLElement("' + val.nodeName + '")'
} else {
ret = 'XML Element("' + val.nodeName + '")'
}
break
case2:
ret = 'ATTRIBUTE_NODE(' + val.nodeName + ')'
break
case3:
ret = 'TEXT_NODE(' + val.nodeValue + ')'
break
case4:
ret = 'CDATA_SECTION_NODE(' + val.nodeValue + ')'
break
case5:
ret = 'ENTITY_REFERENCE_NODE'
break
case6:
ret = 'ENTITY_NODE'
break
case7:
ret = 'PROCESSING_INSTRUCTION_NODE(' + val.nodeName + ':' + val.nodeValue + ')'
break
case8:
ret = 'COMMENT_NODE(' + val.nodeValue + ')'
break
case9:
ret = 'DOCUMENT_NODE'
break
case10:
ret = 'DOCUMENT_TYPE_NODE'
break
case11:
ret = 'DOCUMENT_FRAGMENT_NODE'
break
case12:
ret = 'NOTATION_NODE'
break
}
}
return ret
}
var _formatArray = function (obj, curDepth, padVal, padChar) {
if (curDepth > 0) {
curDepth++
}
const basePad = _repeatChar(padVal * (curDepth - 1), padChar)
const thickPad = _repeatChar(padVal * (curDepth + 1), padChar)
let str = ''
let val = ''
if (typeof obj === 'object' && obj !== null) {
if (obj.constructor && _getFuncName(obj.constructor) === 'LOCUTUS_Resource') {
return obj.var_dump()
}
lgth = 0
for (const someProp in obj) {
if (obj.hasOwnProperty(someProp)) {
lgth++
}
}
str += 'array(' + lgth + ') {\n'
for (const key in obj) {
const objVal = obj[key]
if (typeof objVal === 'object' &&
objVal !== null &&
!(objVal instanceofDate) &&
!(objVal instanceofRegExp) &&
!objVal.nodeName) {
str += thickPad
str += '['
str += key
str += '] =>\n'
str += thickPad
str += _formatArray(objVal, curDepth + 1, padVal, padChar)
} else {
val = _getInnerVal(objVal, thickPad)
str += thickPad
str += '['
str += key
str += '] =>\n'
str += thickPad
str += val
str += '\n'
}
}
str += basePad + '}\n'
} else {
str = _getInnerVal(obj, thickPad)
}
return str
}
output = _formatArray(arguments[0], 0, padVal, padChar)
for (i = 1; i < arguments.length; i++) {
output += '\n' + _formatArray(arguments[i], 0, padVal, padChar)
}
echo(output)
// Not how PHP does it, but helps us test:
return output
}
[ View on GitHub | Edit on GitHub | Source on GitHub ]

How to use

You you can install via npm install locutus and require it via require('locutus/php/var/var_dump'). You could also require the var module in full so that you could access var.var_dump instead.

If you intend to target the browser, you can then use a module bundler such as Parcel, webpack, Browserify, or rollup.js. This can be important because Locutus allows modern JavaScript in the source files, meaning it may not work in all browsers without a build/transpile step. Locutus does transpile all functions to ES5 before publishing to npm.

A community effort

Not unlike Wikipedia, Locutus is an ongoing community effort. Our philosophy follows The McDonald’s Theory. This means that we don't consider it to be a bad thing that many of our functions are first iterations, which may still have their fair share of issues. We hope that these flaws will inspire others to come up with better ideas.

This way of working also means that we don't offer any production guarantees, and recommend to use Locutus inspiration and learning purposes only.

Notes

  • For returning a string, use var_export() with the second argument set to true

Examples

Please note that these examples are distilled from test cases that automatically verify our functions still work correctly. This could explain some quirky ones.

#codeexpected result
1var_dump(1)'int(1)'

« More PHP var functions


Star