Search code examples
javascriptarraysjsonobjectprototype

When iterating an array and print the key and value, also included _proto_ functions, Why?


I made ​​a small script that iterates and prints the values of​​ one JSON object, if the value of the object is another object or an array, 'll call this work to iterate the value (array or object).

This is me presenting a problem when I print the values ​​of the array and print the values ​​that also adds values ​​within __ proto__ like part of the array Note you need to have a <ul> element in your HTML with id jsonUls to get this code working. Code:

   var json = '{"jsonObject":{"value1":"value2", "array1" : ["value1","value2","value3"]}}'; /* Create Json */
   var element = $('#jsonUls');

        var object = JSON.parse(json);  /* Create object */

        /* call the function*/
        recursivePrintObjectValues(object, element); 


        function recursivePrintObjectValues(object, element) {


            for(key in object) { /* Iterate the object */
               var value = object[key]; /*Get the object value */

               /* Verify if value is of type object or an array */
               if(typeof value === 'object' || Array.isArray(value)){

                        /*Generate random */
                        var random = new Date().valueOf() * Math.random() + 351;

                        /* Append Li with key */
                        appendLi(key, '', element);

                        /*Append UL and get the selector*/
                        var ul = appendUl(random, element);

                        /*Call the function with the object and the selector to append (to iterate childs of this object)*/
                        recursivePrintObjectValues(value, ul);
                } else {
                    appendLi(key, value, element);
                }
            }
        }
        function appendUl(random, element) {
            var ul = $('<ul></ul>', {
                        id: random
                     })
                ul.appendTo(element);
            return ul;

        }
        function appendLi(key, value, element) {

            if(value == '[object Object]') {
                value = '';
            }
            $('<li></li>', {
                text: key + ' : '+ value
            }).appendTo(element);
        }

The result is the following and I can't figure why and how to avoid it, hopefully anyone can explain me.

<pre>
    <ul id="jsonUls">
        <li>jsonObject : </li>
        <ul id="448773395479.7797">
            <li>value1 : value2</li>
            <li>array1 : </li>
            <ul id="295240780591.31195">
                <li>0 : value1</li>
                <li>1 : value2</li>
                <li>2 : value3</li>
                <li>$pnmap$ : function $$JSCompiler_prototypeAlias$$$$pnmap$$($f$$30$$,$opt_obj$$28$$){return $goog$array$map$$.apply($JSCompiler_alias_NULL$$,$pn$aargs_$$(this,arguments))}</li>
                <li>$pnforEach$ : function $$JSCompiler_prototypeAlias$$$$pnforEach$$($f$$32$$,$opt_obj$$30$$){$goog$array$forEach$$.apply($JSCompiler_alias_NULL$$,$pn$aargs_$$(this,arguments));return this}</li>
                <li>$pnequals$ : function $$JSCompiler_prototypeAlias$$$$pnequals$$($arr2$$13$$,$opt_equalsFn$$2$$){return $goog$array$equals$$.apply($JSCompiler_alias_NULL$$,$pn$aargs_$$(this,arguments))}</li>
                <li>$pnfindIndex$ : function $$JSCompiler_prototypeAlias$$$$pnfindIndex$$($f$$41$$,$opt_obj$$43$$){return $goog$array$findIndex$$.apply($JSCompiler_alias_NULL$$,$pn$aargs_$$(this,arguments))}</li>
                <li>$pnindexOf$ : function $$JSCompiler_prototypeAlias$$$$pnindexOf$$($obj$$76$$,$opt_fromIndex$$10$$){return $goog$array$indexOf$$.apply($JSCompiler_alias_NULL$$,$pn$aargs_$$(this,arguments))}</li>
            </ul>
        </ul>
    </ul>
</pre>

Solution

  • That's because for...in iterates over properties inherited from the object's prototype too.

    One way to avoid that is check using hasOwnProperty and reject them:

    for(key in object) {
        if (!object.hasOwnProperty(key)) continue;
        // your other code follows
    }
    

    Another option is to use defineProperty to define non-enumerable properties on the prototype, but this will possibly change the behavior of other parts of your code as well.