为什么这个函数适用于文字但不适用于更复杂的表达式?

时间:2009-10-25 14:01:29

标签: javascript debugging types

我有一些我需要帮助的阴险的JavaScript问题。我正在从JSON结构生成HTML。我的想法是,我应该能够传递如下列表:

['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类型的东西,可能与对象文字有关,我不知道。

修改:我已将此代码与我页面上的按钮的点击事件联系起来。每次单击都会向ID为<tbody>的{​​{1}}元素添加一个新行。第一次调用此函数时,kv_body确实为零。但是,一旦我们向混合中添加siblings<tr>会计算出正确的计数,每次添加siblings.length时都会增加。抱歉没有更清楚!! :)

提前感谢您提供任何建议。

3 个答案:

答案 0 :(得分:0)

如果new_id0,是否意味着siblings.length为0?也许真的没有兄弟姐妹。

答案 1 :(得分:0)

也许siblings.length实际上是0?尝试进一步调试(例如使用Firebug)

答案 2 :(得分:0)

好的,我修好了。事实证明,我正在使用第一个函数调用修改我的源JSON对象(因为在JS中你基本上只是传递指针)。我需要编写一个复制函数来创建相关数据的新副本。

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

我最终删除了这个作为原型函数,只是制作一个常规的旧函数。