Почему эта функция работает для литералов, но не для более сложных выражений? - PullRequest
0 голосов
/ 25 октября 2009

У меня какая-то коварная проблема с JavaScript, с которой мне нужна помощь. Я генерирую HTML из структуры JSON. Идея состоит в том, что я должен быть в состоянии передать список как:

['b',{'class':'${class_name}'}, ['i', {}, 'Some text goes here']]

... и получите (если class_name = 'foo') ...

<b class='foo'><i>Some text goes here.</i></b>

Я использую следующие функции:

function replaceVariableSequences(str, vars) {
    /* @TODO Compiling two regexes is probably suboptimal. */
    var patIdent = /(\$\{\w+\})/;  // For identification.
    var patExtr = /\$\{(\w+)\}/;  // For extraction.

    var pieces = str.split(patIdent);

    for(var i = 0; i < pieces.length; i++) {
        if (matches = pieces[i].match(patExtr)) {
            pieces[i] = vars[matches[1]];
        }
     }

     return pieces.join('');
 }

function renderLogicalElement(vars, doc) {
    if (typeof(doc[0]) == 'string') {

        /* Arg represents an element. */

        /* First, perform variable substitution on the attribute values. */
        if (doc[1] != {}) {
            for(var i in doc[1]) {
                doc[1][i] = replaceVariableSequences(doc[1][i], vars);
            }
        }

        /* Create element and store in a placeholder variable so you can
           append text or nodes later. */

        var elementToReturn = createDOM(doc[0], doc[1]);

    } else if (isArrayLike(doc[0])) {

        /* Arg is a list of elements. */
        return map(partial(renderLogicalElement, vars), doc);

    }

    if (typeof(doc[2]) == 'string') {

        /* Arg is literal text used as innerHTML. */
        elementToReturn.innerHTML = doc[2];

    } else if (isArrayLike(doc[2])) {

        /* Arg either (a) represents an element
                   or (b) represents a list of elements. */
        appendChildNodes(elementToReturn, renderLogicalElement(vars, doc[2]));

    }

    return elementToReturn;
}

Иногда это прекрасно работает, но не у других. Пример из телефонного кода:

/* Correct; Works as expected. */
var siblings = findChildElements($('kv_body'), ['tr']);
var new_id = 4;

appendChildNodes($('kv_body'),
                 renderLogicalElement({'id': new_id},
                                      templates['kveKeyValue']));




/* Incorrect; Substitutes "0" for the expression instead of the value of
   `siblings.length` . */
var siblings = findChildElements($('kv_body'), ['tr']);
var new_id = siblings.length;  // Notice change here!

appendChildNodes($('kv_body'),
                 renderLogicalElement({'id': new_id},
                                      templates['kveKeyValue']));

Когда я ловлю первый аргумент renderLogicalElement(), используя alert(), я вижу ноль. Почему это?? Я чувствую, что это какая-то вещь типа JavaScript, возможно связанная с литералами объектов, о которой я не знаю.

Редактировать: Я подключил этот код к событию нажатия кнопки на моей странице. Каждый щелчок добавляет новую строку к элементу <tbody> с идентификатором kv_body. При первом вызове этой функции siblings действительно равен нулю. Тем не менее, как только мы добавим <tr> к миксу, siblings.length оценивается до нужного значения, увеличиваясь при каждом добавлении <tr>. Извините, что не яснее! :)

Заранее благодарим за любой совет, который вы можете дать.

Ответы [ 3 ]

0 голосов
/ 25 октября 2009

Возможно, siblings.length фактически равен 0? Попробуйте продолжить отладку (например, с помощью Firebug)

0 голосов
/ 25 октября 2009

ОК, я исправил это. Как оказалось, я модифицировал исходный объект JSON с помощью первого вызова функции (потому что в JS вы в основном просто передаете указатели). Мне нужно было написать функцию копирования, которая создала бы новую копию соответствующих данных.

http://my.opera.com/GreyWyvern/blog/show.dml/1725165

В итоге я удалил это как функцию-прототип и просто создал обычную старую функцию.

0 голосов
/ 25 октября 2009

Если new_id равно 0, не означает ли это, что siblings.length равно 0? Может быть, в действительности нет родного брата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...