JS: использование eval для функции при попытке передать массив в качестве параметра, но выдает ошибку - PullRequest
0 голосов
/ 23 ноября 2010

Я хочу создать динамически сгенерированную форму, используя JavaScript, все работает нормально, пока я не попытаюсь передать массив в качестве параметра. Когда я делаю это, происходит ошибка. Coulr кто-нибудь объяснит что это?

Вот мой код:

var loadFrm = function(component) {
    for(nItem in component) {
        var myComponent = "add" + firstToUpper(component[nItem].type);
    var callComponent = myComponent + "(" + component[nItem].opt + ");";
    eval(callComponent);
    }
}

var json = [
    {
        type: "scale",
        opt: {content: [{label: "male", value: "m"}, {label: "female", value: "f"}]}
    }
];

loadFrm(json);

Редактировать Вот ошибка:

missing ] after element list
[Break on this error] addScale([object Object]);

Ответы [ 2 ]

4 голосов
/ 23 ноября 2010

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

addScale([object Object])

... это не то, что вы хотите. Это потому, что вы эффективно вызываете toString для вашего opt объекта, и значение по умолчанию toString для объектов выглядит так. Ошибка eval из-за неправильного синтаксиса.

Вообще говоря, всякий раз, когда вы думаете, что вам нужно использовать eval, почти наверняка есть лучший ответ. В этом случае похоже, что вы пытаетесь вызвать функцию и передать opt. Предполагая, что эти функции являются «глобальными», вы можете сделать это следующим образом:

var loadFrm = function(component) {
    var nItem, functionName;

    for (nItem = 0; nItem < component.length; ++nItem) {
        functionName = "add" + firstToUpper(component[nItem].type);
        window[functionName](component[nItem].opt);
    }
}

Живой пример

Примечания к вышесказанному:

  1. Не используйте for..in для циклического перебора массивов, если вы действительно не знаете, что делаете . for..in не перечисляет индексы массива, оно перечисляет свойства объекта.
  2. Мы ищем функцию по имени, используя window[functionName]. Это работает, потому что «глобальные переменные» на самом деле являются свойствами объекта window, и вы можете искать свойства, используя строковое имя для них, используя обозначения в скобках.
  3. Получив функцию через window[functionName], мы просто вызываем ее напрямую, передавая объект opt, а не ее строковую форму. Я предполагаю, что addScale ожидает увидеть объект.
  4. Я переместил все var s в начало функции, потому что именно там они и есть ( details ).
  5. Если вы можете, я бы порекомендовал переместить addScale и связанные с ними функции в их собственный объект, а не помещать их в window. Пространство имен window уже довольно многолюдно. Вот живой пример , модифицированный так, чтобы вообще не добавлять символы к window, вместо этого поместив функцию addScale в объект с именем functions и используя его оттуда.

Не по теме : Синтаксис var loadFrm = function(component) создает анонимную функцию, которую затем назначает переменной. Это часто используется, но если вы не создаете различные функции в зависимости от условия, например ::

var f;
if (...) {
    f = function() { ... };
}
else {
    f = function() { ... };
}

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

Не по теме 2 : у вас есть переменная с именем json, но, к вашему сведению, она не использует запись JSON . Он использует комбинацию массива JavaScript и литеральной нотации объекта, которая является расширенным набором JSON. Вы увидите, что многие люди запутались по этому поводу, я упоминаю об этом, потому что вы сказали, что вы новичок, и поэтому это стоит того. :-) JSON это чисто нотация. (Очень полезный.)

0 голосов
/ 26 марта 2014

Используйте это:

fn = eval(functionName);
fn(objParameter)
...