JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<button onclick="Native();">alert() pure</button>
<button onclick="nativeToString();">alert() with native toString()</button>
<button onclick="Stringfy();">alert() with JSON.stringify</button>
<button onclick="ToString();">alert() with ToString()</button>
<pre>Click to see...</pre>

CSS

button {
  display: block;
  width: 50%;
}

JavaScript

window.Native = function() {
    var result = new MyObject();
    $("pre").html(String(result));
}

window.nativeToString = function() {
    var result = new MyObject().toString();
    $("pre").html(String(result));
}

window.Stringfy = function() {
    var result;
    try {
        result = JSON.stringify(new MyObject());
    }
    catch (e) {
        result = "ERROR: " + e.message;
    }
    $("pre").html(String(result));
}

window.ToString = function() {
    var result = ToString(new MyObject());
    $("pre").html(String(result));
}

var MyObject = function() {
    this.prop1 = "Hello World";
    this.prop2 = "LOL";
    this.recursive = this;
    this.func = function() { return "func return"; }
}

function ToString(obj) {
    clearTimeout(window.ToStringTimeout);

    var result;
    var ident = arguments.length >= 2 ? arguments[1] : undefined;

    if (obj == null) {
        result = String(obj);
    }

    if (!result) {
        window.ToStringRecursive = window.ToStringRecursive ? window.ToStringRecursive : [];
        if (ToStringRecursive.indexOf(obj) >= 0) {
            result = obj ? (typeof(obj) == "string" ? "\"" + obj + "\"" : obj.toString()) : obj;
        } else {
            ToStringRecursive.push(obj);
        }
        if (!result) {
            switch (typeof obj) {
                case "string":
                    result = '"' + obj + '"';
                    break;
                case "function":
                    result = obj.name || obj.toString();
                    break;
                case "object":
                    var indent = Array(ident || 1).join('\t'),
                        isArray = Array.isArray(obj);
                    result = '{[' [+isArray] + Object.keys(obj).map(
                        function(key) {
                            return '\n\t' + indent + key + ': ' + ToString(obj[key], (ident || 1) + 1);
                        }).join(',') + '\n' + indent + '}]' [+isArray];
                    break;
          ...