Javascript DOM中通过前置元素的无限循环

Javascript DOM中通过前置元素的无限循环,javascript,dom,internet-explorer-6,infinite-loop,Javascript,Dom,Internet Explorer 6,Infinite Loop,不寻找使用框架XXX答案 这个问题不是为了通过一个框架找到一个实际的解决方案。回答使用框架XXX,或者这在框架XXX中很容易,或者为什么不使用这个框架XXX???没有回答这个问题 我有一个在加载页面后运行的函数:performShim。此函数迭代DOM中属于span标记的所有元素,检查它们是否有className的shim,如果有,则调用shim向其传递匹配元素的引用 我的目标是为传递给shim的元素预先添加另一个span,其中包含iframe 使用到目前为止我编写的代码,我能够很好地附加到元素

不寻找使用框架XXX答案

这个问题不是为了通过一个框架找到一个实际的解决方案。回答使用框架XXX,或者这在框架XXX中很容易,或者为什么不使用这个框架XXX???没有回答这个问题

我有一个在加载页面后运行的函数:
performShim
。此函数迭代DOM中属于
span
标记的所有元素,检查它们是否有
className
shim
,如果有,则调用
shim
向其传递匹配元素的引用

我的目标是为传递给
shim
的元素预先添加另一个
span
,其中包含
iframe

使用到目前为止我编写的代码,我能够很好地附加到元素的父元素。但是,如果我注释掉
append
行,而尝试使用prepend行,那么浏览器可能挂起在一个无限循环中

我不太清楚为什么会这样

function shim( element ) {      
    var iframe = document.createElement('iframe');
    iframe.setAttribute( 'frameborder', '0' );
    iframe.setAttribute( 'scrolling', 'no' );
    iframe.setAttribute( 'align', 'bottom' );
    iframe.setAttribute( 'marginheight', '0' );
    iframe.setAttribute( 'marginwidth', '0' );
    iframe.setAttribute( 'src', "javascript:'';" ); 

    var span = document.createElement('span');
    span.appendChild(iframe);


    //element.parentNode.insertBefore(span,element); //causes infinite loop?

    element.parentNode.appendChild(span); //this line works OK

    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    var originalDisplay = els.display;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = 'inline';
    var width = element.offsetWidth;
    var height = element.offsetHeight;
    els.display = originalDisplay;
    els.position = originalPosition;
    els.visibility = originalVisibility;

    iframe.style.width = (width-6) + 'px';
    iframe.style.height = (height-6) + 'px';

}   

function performShim() {
    var children = document.getElementsByTagName("span");   
    for( var i = 0; i < children.length; i++ ) {
        if( children[i].className == "shim" ) {
            shim(children[i]);  
        }
    }
} 
功能垫片(元素){
var iframe=document.createElement('iframe');
setAttribute('frameborder','0');
setAttribute('scrolling','no');
setAttribute('align','bottom');
setAttribute('marginheight','0');
setAttribute('marginwidth','0');
setAttribute('src','javascript:“”;“”);
var span=document.createElement('span');
span.appendChild(iframe);
//element.parentNode.insertBefore(span,element);//导致无限循环?
element.parentNode.appendChild(span);//此行正常
var els=element.style;
var原始可视性=els.可视性;
变量原始位置=els位置;
var originalDisplay=els.display;
els.visibility=‘隐藏’;
els.position=‘绝对’;
els.display='inline';
变量宽度=element.offsetWidth;
var高度=元素。偏离视线;
els.display=原始显示;
els.位置=原始位置;
els.可见性=原始可见性;
iframe.style.width=(width-6)+“px”;
iframe.style.height=(height-6)+“px”;
}   
函数performShim(){
var children=document.getElementsByTagName(“span”);
对于(变量i=0;i
A
NodeList
(如
document.getElementsByTagName
返回的节点列表)通常是一个活动列表——您对DOM所做的更改也会显示在其中。因此,每次在当前元素之前添加
span
,都会将列表扩展一个元素,并将当前元素移动一个元素,下一次迭代会将您放回刚刚完成的节点

你有几个简单的解决办法

  • 添加节点时碰撞计数器。(很难看,如果你最终添加了一些东西而不是
    span
    ,你最终会跳过节点,原因也不清楚。)

  • 将列表复制到一个数组,并在该数组上迭代。您可以使用类似
    children=[].slice.call(children,0)(更常见)或
    children=Array.apply(窗口,子对象)

  • 使用
    document.querySelectorAll
    ,它将返回一个非活动的节点列表。(即使它是活动的,在这种情况下,您可以选择
    'span.shim'
    ,插入的跨距也不会显示在其中。)

  • 向后迭代(从
    childrence.length-1
    到0)


这个问题不是为了找到一个实用的解决方案
那么它就错了。@LightnessRacesinOrbit:你通过一个框架忽略了[…],这是一个非常合理的要求。很抱歉,这个问题是为了更好地理解DOM和与DOM相关的纯javascript函数,没有更好地理解框架如何让您的生活更轻松。我对给出的答案很满意。@Felix:你忽略了我的史诗humour@LightnessRacesinOrbit当前位置也许我的幽默感被这一票的微弱优势蒙蔽了双眼,而这一票似乎与你的评论有关。道歉,不要难过;)+1.下一次迭代将您放回刚刚完成的节点,这是重要的部分。追加是“好的”(在本例中),因为在下一次迭代中,您将处理另一个节点,并且最终您将使用类
shim
耗尽
span
节点。但是,如果生成的
span
s也被分配了
shim
类,它也会生成一个无限循环。那么在
performShim
中,变量
children
是否只是对活动列表的引用?如果是这样的话,为什么附加
span
就可以了,而预加就不行了?@user1169578:请看我的评论。关于准备,考虑节点<代码> A,B < /代码>。循环变量是
i=0
。现在您正在处理
a
并在节点
c
前加前缀。结果是
c、a、b
。循环变量前进到
i=1
,这也是节点
a
。。。等等。如果你改为追加,你的列表可能看起来像
a、b、c
,一旦你处理
c
你就不会再追加任何节点,因为
c
没有类
shim
。如果你使用
。queryselectoral()
你可以按类选择,所以(在这种情况下)返回是否有效并不重要。对于选择所有跨度的现有代码,您可以向后迭代循环。谢谢,我想通过函数(如
getElementsByTagName
)检索的集合是一个活动集合,这一点很微妙。我选择将初始集合复制到一个数组,并在该数组上迭代。感谢大家对这一微妙的解释,但我相信