2

I'm trying write a function to convert an Array to a DocumentFragment. Each item of the array will become an HTMLElement. It's tag name will be the array-item's class name*, and its attributes will be the properties of the array-item whose values are strings.

So for example, if I have these constructors:

function Person(name,pets){
        this.name=name;
        this.pets=pets;
    }
function Pet(name){this.name=name;}

And this data:

var arr=[
        new Person("Bob",[
            new Pet("Sparky"),
            new Pet("Wishbone")
        ]),
        new Person("Mary",[
            new Pet("Maggie"),
            new Pet("Sprinkles")
        ])
    ];

I use this function and it works great:

Array.prototype.toDocFrag=function(){
        return this.reduce(function(docFrag,currentItem){
            elem=document.createElement(currentItem.constructor.name.toLowerCase());
            for (prop in currentItem){
                if (typeof currentItem[prop]==="string") elem.setAttribute(prop,currentItem[prop])
                //if (currentItem[prop] instanceof Array) elem.appendChild(currentItem[prop].toDocFrag())
            }
            docFrag.appendChild(elem)
            return docFrag;
        },document.createDocumentFragment())
    }

If I run arr.toDocFrag(), I get a docFrag with the contents <person name="Bob"></person><person name="Mary"></person> as expected.

But now what I want to do is make it recursive, so that it sees "pets" and appends another DocumentFragment to each <person> so I end up with

<person name="Bob">
    <pet name="Sparky"></pet>
    <pet name="Wishbone"></pet>
</person>
<person name="Mary">
    <pet name="Maggie"></pet>
    <pet name="Sprinkles"></pet>
</person> 

Uncomment out the line I commented out in my code, and I believe that it should work. But for some reason arr.toDocFrag() is returning just <pet name="Wishbone"></pet><pet name="Sprinkles"></pet>

What is wrong with my logic? Am I misunderstanding something about Array.prototype.reduce or recursive functions?

Thanks!


Footnote

*By class name I mean the name of the constructor that initiates the instance.

1 Answer 1

4

Your problem is that elem is an implicitly global variable. This doesn't matter for your first function, but completely messes up the recursive function where a call overwrites elem of his caller.

Use a var statement to declare your variables locally (it's missing for prop as well). And use strict mode to get errors on such behaviour.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.