Как запустить объект JavaScript из строки без использования eval()

У меня есть объект json, который имеет тип элемента и идентификатор, мне нужно создать новый объект

var data = { 
            "items":[
                    {"type":"generator","id":"item_1","x":200,"y":200},
                    {"type":"battery","id":"item_2","x":50,"y":300},
                    {"type":"generator","id":"item_3","x":200,"y":280},
                    {"type":"battery","id":"item_4","x":100,"y":400}
                ]
        };

и мне нужно работать для каждого элемента в элементах

jQuery.each(data.items, function(index,value) {
    eval("var " + value.id + " = new " + value.type + "(" + (index + 1) + ");");
    eval(value.id + ".id = '" + value.id + "';");
    eval(value.id + ".draw(" + value.x + "," + value.y + ");")
});

это не очень хорошая практика, но что еще я могу сделать?

Мне нужно, чтобы иметь контроль над элементами

что-то вроде

    item_1.moveto(300,700);

но я всегда получаю item_1 не определен

2 ответа

Решение

Вы можете создать фабричный метод, который позволяет генерировать конкретные типы из абстрактной структуры данных:

var createItem = (function () {
    var types = {};

    function createItem(index, data) {
        data = data || {};

        var ctor = types[data.type], item;

        if (!ctor) throw new Error("'" + data.type + "' is not a registered item type.");

        item = new ctor(index);

        item.id = data.id;

        return item;
    }

    createItem.registerType = function (type, ctor) {
        types[type] = ctor;
    };

    return createItem;

})();

Затем зарегистрируйте типы элементов на заводе:

function Generator(index) {/*...*/}

createItem.registerType('generator', Generator);

И, наконец, создайте карту объектов, чтобы искать ваши элементы по идентификатору (вы можете использовать специализированный объект, например ItemsMap вместо простого объекта), проходить по вашим элементам и добавлять их на карту.

var itemsMap = {};

data.items.forEach(function (itemData, i) {
    var item = itemsMap[itemData.id] = createItem(i + 1, itemData);

    //you can also draw them at this point
    item.draw(itemData.x, itemData.y);
});

Теперь вы можете искать объекты по идентификатору, например:

var item1 = itemsMap['item_1'];
var objects = {};

objects[value.id] = new window[value.type](index + 1);
Другие вопросы по тегам