Prototype1.5 诡异错误一例
2010-09-14 13:21:59 来源:WEB开发网示范代码:<divid="test-parent">
<divclass="test-child">child</div>
</div><script>
//获取childdiv
varc=document.getElementsByClassName(’test-child’)[0];
//克隆一份childdiv
newInsertion.After(c,$(’test-parent’).innerHTML);
//获取克隆后插入的第二个div
varc2=$$(’.test-child’)[1];
c2.hide();//Error:Objectdoesn’tsupportthispropertyormethod
</script>
从Prototype1.5开始,$()、$$()和getElementsByClassName()这三个方法取得的结果对象,在返回前Prototype都会用Element.extend(elm)函数进行封装。这样结果对象就自动拥有了Element对象的很多实例方法,原来比如
Element.hide(element);
这样的调用可以简化为
$(element).hide();
那么开头部分代码报错的原因何解呢?打印出"$(’test-parent’).innerHTML"的输出可看出些端倪来,IE7的输出结果如下:
<DIVclass=test-child_extended="true">child</DIV>
奥妙就在这个_extended属性上,看Element.extend()的源码
Element.extend=function(element){
原来Element.extend(elm)方法会给element增加一个_extended属性,当element再次被$()等函数取得并返回时如果发现已经有了这个属性则停止执行。
if(!element)return;
if(_nativeExtensions)returnelement; if(!element._extended&&element.tagName&&element!=window){
varmethods=Element.Methods,cache=Element.extend.cache;
for(propertyinmethods){
varvalue=methods[property];
if(typeofvalue==’function’)
element[property]=cache.findOrStore(value);
}
} element._extended=true;
returnelement;
}
所以,开头代码报错的原因就在于通过innerHTML复制一个element的时候,_extended也被复制了进去,这样被复制后插入的新element就无法继承到Element的实例方法。对新element调用这些实例方法时就抛出错误来。
解决办法
从innerHTML中过滤掉_extended属性
手工清除新对象的_extended属性后重新调用$()
用DOM方法替换innerHTML
更多精彩
赞助商链接