Help us understand the problem. What is going on with this article?

引数に渡された値を詳細に表示

More than 5 years have passed since last update.

初投稿です。
タイトルのような関数を作ってみました。

一定のコーディング規約を決めて書きました。
ソースコードは全て英語ですが、英和/和英辞典で調べて、それっぽいものを使っただけです。
変な英語表現がありましたら、教えて下さい。(一杯ありそうです)

使い方

 debug([1,2])

とすると、

 [
     1,
     2
 ]

という感じです。
使ってみれば分かります。
オプションでは、indent(インデント) と depth(階層) が指定できます。
depth 0 では、階層の概念なし、ということで、オブジェクトを完全に展開します。
debug([1,2],{depth:0}) とすれば、上記と同じ内容が返ります。
depth 1 では、1階層分の展開しかしません。
debug([1,2],{depth:1}) とすれば、[object Array] が返ります。
depth 2 では 上記と同じ内容が返ります。
これ、説明し辛いです。

indent は、その名の通り、インデントの文字を指定できます。
' ' を指定すれば、空白2つ分ですし、
'\t' を指定すれば、水平タブ1つ分です。
'___' こんなのでも指定できます。

それから、DOM 辺りの扱いが適当です。
window なんかも、エラー出ないようにに取り繕いました。

/* option
    .indent
        '': no indent
        '  ': indent with '  '
    .depth
        0: all expand (no - depth)
        1: no expand (depth 1)
        2: 1 expand (depth 2)
*/
(function(global, undef){
'use strict';
var
    toString = Object.prototype.toString,
    hasOwnProperty = Object.prototype.hasOwnProperty,

    Indent,
    MaximumDepth,

    // Boolean
    limitDepth;
var makeSource = function (CurrentDepth, stack, value) {
    var

        // Boolean
        circulated,

        // String
        currentIndent = '',

        // Number
        formerDepth,
        i,
        index,
        length,
        stackLength,

        // Object
        array,
        attributes,
        constructor,

        // Node for NamedNodeMap
        node;

    // undefined null
    switch (value) {
    case undef:
        return 'undefined';
    case null:
        return 'null';
    default:
        break;
    }

    try {
        constructor = value.constructor;
    } catch (e) {
        return '[' + toString.call(value) + ']';
    }

    // Not (DOM | Window)
    if ('function' === typeof constructor) {
        switch (toString.call(value)) {
        case '[object Boolean]':
            return value.toString();
        case '[object String]':
            return '\'' + value.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + '\'';
        case '[object Number]':
            return value.toString();
        case '[object Date]':
            return value.toGMTString();
        case '[object RegExp]':
            return value.toString();
        case '[object Function]':
            return 'function ' + (value.name || '');
        case '[object Array]':
            // Limit Depth
            if (MaximumDepth && CurrentDepth >= MaximumDepth) {
                return '[object Array]';
            }

            // Check Circular Reference
            circulated = false;
            i = stackLength = stack.length;
            while (i--) {
                if (value === stack[i]) {
                    circulated = true;
                    break;
                }
            }
            if (circulated) {
                return 'circular referenced Array';
            }

            // Push Stack
            stack[stackLength] = value;

            // make indent
            i = CurrentDepth;
            while (--i) {
                currentIndent += Indent;
            }

            // make source again
            array = [];
            length = value.length;
            for (i = 0; i < length; ++i) {
                array[i] = '\n' + currentIndent + Indent + makeSource(CurrentDepth + 1, stack, value[i]);
            }

            // Pop Stack
            stack.length = stackLength;

            return '[' + array.join(',') + '\n' + currentIndent + ']';
        case '[object Object]':
            // Limit Depth
            if (MaximumDepth && CurrentDepth >= MaximumDepth) {
                return '[object Object]';
            }

            // Check Circular Reference
            circulated = false;
            i = stackLength = stack.length;
            while (i--) {
                if (value === stack[i]) {
                    circulated = true;
                    break;
                }
            }
            if (circulated) {
                return 'circular referenced Object';
            }

            // Push Stack
            stack[stackLength] = value;

            // make indent
            i = CurrentDepth;
            while (--i) {
                currentIndent += Indent;
            }

            // make source again
            index = 0;
            array = [];
            for (i in value) {
                if (hasOwnProperty.call(value, i)) {
                    array[index++] = '\n' + currentIndent + Indent + '\'' + i.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + '\': ' + makeSource(CurrentDepth + 1, stack, value[i]);
                }
            }

            // Pop Stack
            stack.length = stackLength;

            return '{' + array.join(',') + '\n' + currentIndent + '}';
        default:
            break;
        }
    } else {
        switch (value.nodeType) {
        // ELEMENT_NODE
        case 1:
            // Limit Depth
            if (MaximumDepth && CurrentDepth >= MaximumDepth) {
                return '[' + toString.call(value) + ']' + ' (nodeType - ' + value.nodeType + ')';
            }

            // make indent
            i = CurrentDepth;
            while (--i) {
                currentIndent += Indent;
            }

            // make source again
            if (length = (attributes = value.attributes).length) {
                array = [];
                for (i = 0; i < length; ++i) {
                    array[i] = '\n' + currentIndent + Indent + makeSource(CurrentDepth + 1, stack, attributes[i]);
                }
                return '[' + value.toString() + ']' + '{' + array.join(',') + '\n' + currentIndent + '}';
            } else {
                return '[' + value.toString() + ']';
            }
        case 2:
            return 'ATTRIBUTE_NODE{' + value.name + ': ' + value.value + '}';
        case 3:
            return 'TEXT_NODE[' + value.nodeValue + ']';
        case 4:
            return 'CDATA_SECTION_NODE[' + value.nodeValue + ']';
        case 5:
            return 'ENTITY_REFERENCE_NODE[' + value.nodeValue + ']';
        case 6:
            return 'ENTITY_NODE[' + value.nodeValue + ']';
        case 7:
            return 'PROCESSING_INSTRUCTION_NODE[' + value.nodeValue + ']';
        case 8:
            return 'COMMENT_NODE[' + value.nodeValue + ']';
        case 9:
            return 'DOCUMENT_ELEMENT(document)';
        case 10:
            return 'DOCUMENT_TYPE_NODE';
        case 11:
            return 'DOCUMENT_FRAGMENT_NODE';
        case 12:
            return 'NOTATION_NODE';
        // NamedNodeMap
        default:
            if (undef !== value.getNamedItem) {
                // make indent
                i = CurrentDepth;
                while (--i) {
                    currentIndent += Indent;
                }

                // make source again
                if (length = value.length) {
                    array = [];
                    for (i = 0; i < length; ++i) {
                        array[i] = '\n\'' + (node = value[i]).name.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + '\': \'' + (node.value || '').replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + '\'';
                    }
                    return 'NamedNodeMap' + '{' + array.join(',') + '\n' + currentIndent + '}';
                } else {
                    return 'NamedNodeMap';
                }
            }
            break;
        }
    }

    // Limit Depth
    if (limitDepth || MaximumDepth && CurrentDepth >= MaximumDepth) {
        return '[' + toString.call(value) + ']';
    }

    if (undef === (length = value.length)) {
        // Others
        return '[' + toString.call(value) + ']' + ' (Stranger)';
    } else {
        if ('number' === typeof length && hasOwnProperty.call(value, length - 1)) {
            // Check Circular Reference
            circulated = false;
            i = stackLength = stack.length;
            while (i--) {
                if (value === stack[i]) {
                    circulated = true;
                    break;
                }
            }
            if (circulated) {
                return 'circular referenced Arrayed Stranger';
            }

            // Push Stack
            stack[stackLength] = value;

            // make indent
            i = CurrentDepth;
            while (--i) {
                currentIndent += Indent;
            }

            // limit depth
            limitDepth = true;

            // make source again
            length = value.length;
            array = [];
            for (i = 0; i < length; ++i) {
                array[i] = '\n' + currentIndent + Indent + makeSource(CurrentDepth + 1, stack, value[i]);
            }

            // free depth
            limitDepth = false;

            // reposit MaximumDepth
            MaximumDepth = formerDepth;

            // Pop Stack
            stack.length = stackLength;

            return '[' + toString.call(value) + ']' + '[' + array.join(',') + '\n' + currentIndent + ']';
        } else {
            // Check Circular Reference
            circulated = false;
            i = stackLength = stack.length;
            while (i--) {
                if (value === stack[i]) {
                    circulated = true;
                    break;
                }
            }
            if (circulated) {
                return 'circular referenced Objected Stranger';
            }

            // Push Stack
            stack[stackLength] = value;

            // make indent
            i = CurrentDepth;
            while (--i) {
                currentIndent += Indent;
            }

            // limit depth
            limitDepth = true;

            // make source again
            index = 0;
            array = [];
            for (i in value) {
                if (hasOwnProperty.call(value, i)) {
                    array[index++] = '\n' + currentIndent + Indent + '\'' + i.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + '\': ' + makeSource(CurrentDepth + 1, stack, value[i]);
                } else {
                    array[index++] = '\n' + currentIndent + Indent + '\'' + i.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + '\': ' + makeSource(CurrentDepth + 1, stack, value[i]) + ' (prototype)';
                }
            }

            // free depth
            limitDepth = false;

            // Pop Stack
            stack.length = length;

            return '[' + toString.call(value) + ']' + '{' + array.join(',') + '\n' + currentIndent + '}';
        }
    }
};
global.debug = function (object, option) {
    var hasOwnProperty = Object.prototype.hasOwnProperty;

    /* option */
    if (option) {
        // String indent
        if (hasOwnProperty.call(option, 'indent')) {
            Indent = option.indent;
        } else {
            Indent = '   ';
        }

        // Number depth
        if (hasOwnProperty.call(option, 'depth')) {
            MaximumDepth = option.depth;
        } else {
            MaximumDepth = 0;
        }
    } else {
        Indent = '   ';
        MaximumDepth = 0;
    }

    return makeSource(1, [], object);
};
})(this);
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした