发生了什么?有一天它可以,第二天它'未定义'?

时间:2011-05-08 06:55:46

标签: javascript greasemonkey undefined firefox4

我正在撰写一个关于我的文章。最近我有两次同样的问题,我不知道为什么会这样。

function colli(){
.....
var oPriorityMass = bynID('massadderPriority');//my own document.getElementById() function
var aPriorities = [];
if (oPriorityMass) {
    for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
        var sCollNumber = oPriorityMass.childNodes[cEntry].getAttribute('coll');
        if (bynID('adder' + sCollNumber + '_check').checked)
            aPriorities.push(parseInt(sCollNumber));
    }
}
.....
}

所以,有一天我将oPriorityMass命名为oPririoty。它工作正常,但整个功能还没有完成,我开始为我的脚本工作另一个功能。这些功能彼此没有关系。

几天后我决定回到上面例子中的功能并完成它。我在没有修改任何内容的情况下对其进行了测试,并在firefox的(4)javascript错误控制台中出现错误oPriority.chilNodes[cEntry] is undefined。注意,几天前我已经完全按照相同的方式测试它,并且根本没有这样的问题。

好的,我决定将oPriority重命名为oPriorityMass。神奇地,问题得到了解决。

起初我想,也许有两个对象的冲突,在不同的功能中使用相同的名称,即使在功能范围之外,它们仍以某种方式继续存在。我的脚本目前超过6000行,但我进行了搜索,发现oPriority在其他任何地方都没有被提及,但在这个确切的功能中。

有人可以告诉我,这是怎么回事以及为什么会这样?我提到同样的事情现在发生了两次,它们发生在不同的功能中,但同样的问题node.childNodes[c] is undefinednode不是空的而node.childNodes.length显示正确的子计数。 到底是怎么回事?我该如何避免这些问题?

谢谢

编辑:错误控制台提供的错误是 Error: uncaught exception: TypeError: oPriorityMass.childNodes[cEntry] is undefined

回应布洛克斯评论: GM_log(oPriorityMass.childNodes[cEntry])会将undefined作为消息返回。所以node.childNodes[c]是一般未定义的东西。

我的脚本创建了一个div窗口。后来,上面的函数使用了这个div中的元素。元素确实有唯一的ID,我100%确定原始网站不知道它们。 我的脚本有一个开始/停止按钮,可以在需要时运行一个或另一个功能。 我一直在刷新页面并运行我的脚本功能。我注意到有时(但不总是)脚本会在第一次运行时因所描述的错误而失败,但是,如果我再次运行它(不刷新页面),它就会开始工作。

该页面有一个修改它的JavaScript。它会改变它的一些元素宽度,以便在调整浏览器大小时更改它。但我知道它对我的div没有影响,因为当我调整浏览器大小时它保持不变。

EDIT2

function bynID(sID) {
    return top.document.getElementById(ns(sID));
}
function ns(sText) {
    return g_sScriptName + '_' + sText;
}

ns函数只是在ID前添加脚本名称。我在创建HTML元素时使用它,因此我的元素永远不会与网页具有相同的ID。所以bynID()是一个简单的函数,当我需要按ID获取元素时,可以节省一些打字时间。

我修改了colli()功能以包含检查

if (oPriorityMass) {
    if (!oPriorityMass.childNodes[0]) {
        GM_log('Retrying');
        setTimeout(loadPage,2000);
        return;
    }
    for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
        var sCollNumber = oPriorityMass.childNodes[cEntry].getAttribute('coll');
        if (bynID('adder' + sCollNumber + '_check').checked)
            aPriorities.push(parseInt(sCollNumber));
    }
}

loadPage函数执行1次AJAX调用,然后我在其上运行了几个XPATH查询,但实际内容从未在页面上附加/显示,只保留在document.createElement('div')内,然后此函数调用colli()。所以现在,因为我修改了我的功能,我检查了错误控制台,发现它可能需要多达5次尝试才能开始正常工作。 5 x 2秒,即10秒。永远不会有5次重试,可能会有所不同还有其他事情要继续吗?

2 个答案:

答案 0 :(得分:0)

在Firefox中,childNodes可以包含#text节点。在尝试调用之前,您应该检查以确保childNodes[cEntry]具有nodeType == 1getAttribute方法。 e.g。

<div id="d0">
</div>
<div id="d1"></div>

在上面的Firefox和类似的浏览器中(即基于Gecko和基于WebKit的浏览器,如Safari),d0有一个子节点,一个文本节点,而d1没有子节点。

所以我会这样做:

var sCollNumber, el0, el1;

if (oPriorityMass) {
    for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
        el0 = oPriorityMass.childNodes[cEntry];

        // Make sure have an HTMLElement that will
        // have a getAttribute method
        if (el0.nodeType == 1) {
          sCollNumber = el0.getAttribute('coll');
          el1 = bynID('adder' + sCollNumber + '_check');

         // Make sure el1 is not falsey before attempting to
         // access properties
         if (el1 && el1.checked)

            // Never call parseInt on strings without a radix
            // Or use some other method to convert to Number
            aPriorities.push(parseInt(sCollNumber, 10));
    }
}

鉴于sCollNumber似乎是一个字符串整数(只是猜测,但似乎很可能),你也可以使用:

Number(sCollNumber)

+sCollNumber

适合哪种情况并且更易于维护。

答案 1 :(得分:0)

所以,根据你的上一次编辑,它现在有效,延迟,对吧?

但是当我提出延迟时,它不打算做(甚至更多?)ajax在等待时调用!!

不会

if (!oPriorityMass.childNodes[0]) {
    GM_log('Retrying');
    setTimeout(loadPage,2000);
    return;

更像是:

setTimeout (colli, 2000);

所以ajax和loadPage所做的其他事情可以解释过度延迟。


随机行为可能由以下原因引起:

return top.document.getElementById(ns(sID));

如果存在任何帧或iframe,这将导致不稳定的行为,并且您不会阻止对帧的操作。 (如果您执行阻止此类操作,则top是多余且不必要的。)
在这种情况下,GM无法正常运行 - 取决于脚本的功能 - 通常看起来从顶级范围“切换”到帧范围,反之亦然。

因此,最好将其更改为:

return document.getElementById (ns (sID) );


并确保你有:

if (window.top != window.self)  //-- Don't run on frames or iframes
    return;

作为顶行代码。


除此之外,由于信息不足,几乎不可能看到问题。

将问题分解为完整自包含配方以复制失败。

或者,发布或链接到完整未经编辑脚本