Where do I need a closure for this one?

I have this constructor:

var EditableItem = (function() {

    function EditableItem(schema, item) {
        this.schema = _.clone(schema);
        this.item = _.clone(item);
        this.propertyTypes = [
            'stringProperties',
            'booleanProperties'];
    }

    EditableItem.prototype = {
        createItem: function() {
            var self = this;
            self.propertyTypes.forEach(function(type) {
                var properties = self.schema[type];
                properties.forEach(function(property, i) {
                    var itemProperty = self.item[type][property.id];
                    if (itemProperty) {
                        properties[i].value = itemProperty;
                    }
                });
            });

            self.schema.itemId = self.item._id;

            return self.schema;
        }
    };

    return EditableItem;

})();

and each time I use it, like this...

async.parallel({
    schema: function(callback) {
        schemas().findOne({
            _id: 'default'
        }, callback);
    },
    items: function(callback) {
        items().find().toArray(callback);
    }
},

function(err, result) {
    if (err) return callback(err);

    var all = result.items.map(function(item) {
        return new EditableItem(result.schema, item).createItem();
    });

    callback(null, all);
});

...I end up with an array result where the last item is repeated while the others are omitted.

My guess is that I need to add a closure somewhere, and as you can see I've tried, but still it yields the same result. Any ideas?

EDIT: I've found a solution. It's not pretty, but maybe someone here can explain why it works and offer a better solution...

In the constructor, where I had: this.schema = _.clone(schema);

I changed to: this.schema = JSON.parse(JSON.stringify(schema));

This seems to allocate new memory for the object, while _.clone still keeps some references to the original object (I guess).

Javascript numbers, strings & booleans are equated and passed by value while objects and arrays are equated and passed by reference. As a JSON representation of an object is a string, it will be equated and passed by value.

If working with a JSON representation of schema gives different behaviour from a clone (an object), then we may conclude that the clone still contains references to the same objects as the original, uncloned schema; ie. the clone is not "deep".

As I understand it, underscore.js doesn't yet offer deep clone but Lo_Dash does. You might like to try Lo_Dash's underscore compatibility build.

Alternatively, just stick with your JSON approach, which is doing the same for you as a more formal deep clone method.