首页 » 编写高质量代码:改善JavaScript程序的188个建议 » 编写高质量代码:改善JavaScript程序的188个建议全文在线阅读

《编写高质量代码:改善JavaScript程序的188个建议》建议163:关注各种引擎对DOM解析的分歧

关灯直达底部

1.通过ID访问HTML元素

对于IE来说,可以使用eval(/"idName/")或getElementById(/"idName/")获取ID为idName的HTML元素,但非IE浏览器只能使用getElementById(/"idName/")来获取ID为idName的HTML元素。通过ID访问HTML元素一般直接使用document.getElementById就可以了。


<input type=/"button/"id=/"myButton/">

<script>

alert(document.getElementById(/"myButton/").value);

</script>


为了兼容低版本的IE,可以加上document.all。

提示:IE还支持把HTML元素的ID名作为document对象的属性名直接使用,如document.idName。但其他引擎是不支持这种用法的,建议禁止使用。同时不要定义与HTML元素ID相同的变量名,以减少错误。在声明变量时一律加上var关键字,以避免产生歧义。

2.集合类对象问题

在IE中可以使用或获取集合类对象,而在非IE浏览器中只能使用获取集合类对象,解决方法就是统一使用获取集合类对象。

例如,访问表单元素form,传统方法支持使用document.form.item访问表单对象,但IE允许document.formName.item(/"itemName/")或document.formName.elements[/"elementName/"]用法,Firefox等引擎仅支持document.formName.elements[/"elementName/"]用法。若想要兼容IE、Firefox等浏览器都能够正常运行,那么需要规范化访问表单对象的方法,统一使用document.formName.elements[/"elementName/"]。


<body>

<form.name=/"myForm/">

<input id=/"txt/"/>

</form>

</body>

<script>

alert(document.myForm.elements[/"txt/"].value);

</script>


在Firefox中,在访问数组时不能使用类似arr(/"itemName/")的形式,必须使用中括号,而在IE中两者都可以。在使用时应该注意代码的规范性,例如,下面两种不同的写法在Firefox等引擎中有不同的返回结果。

(1)错误写法


<form.name=/"myForm/">

<input id=/"txt/"/>

</form>

<script>

alert(document.myForm);

alert(document.forms.length);//返回0,错误

</script>


(2)正确写法


<body>

<form.name=/"myForm/">

<input id=/"txt/"/>

</form>

</body>

<script>

alert(document.myForm);

alert(document.forms.length);//返回1,正常

</script>


3.删除节点

IE支持使用removeNode方法删除节点。


<input type=/"button/"id=/"myButton/">

<script>

document.getElementById(/"myButton/").removeNode;

</script>


但Firefox等引擎没有这个方法,只能先找到父节点,然后调用DOM的removeChild方法才可以删除节点。不过IE也支持这种方法。


<input type=/"button/"id=/"myButton/">

<script>

var Node=document.getElementById(/"myButton/");

oNode.parentNode.removeChild(oNode);

</script>


4.交换节点

IE支持使用swapNode私有方法来交换两个HTML元素节点。


<input type=/"button/"id=/"firstButton/">

<input type=/"button/"id=/"secondButton/">

<script>

var First=document.getElementById(/"firstButton/");

var Second=document.getElementById(/"secondButton/");

oFirst.swapNode(oSecond);

</script>


但Firefox不支持这种方法,要实现相同的操作,需要自定义函数。


<input type=/"button/"id=/"firstButton/">

<input type=/"button/"id=/"secondButton/">

<script>

if(window.Node){

Node.prototype.swapNode=function(node){

var nextSibling=this.nextSibling;

var parentNode=this.parentNode;

node.parentNode.replaceChild(this,node);

parentNode.insertBefore(node,nextSibling);

}

}

var First=document.getElementById(/"firstButton/");

var Second=document.getElementById(/"secondButton/");

oFirst.swapNode(oSecond);

</script>


5.插入节点

IE支持使用insertAdjacentHTML和insertAdjacentElement两个私有方法来插入HTML节点。


<p></p>

<script>

var Div=document.getElementById(/"p1/");

var htmlInput=/"<input>/";

oDiv.insertAdjacentHTML(/'beforeEnd/',htmlInput);

</script>


但Firefox中没有这两个方法,为了兼容它们,可以统一使用DOM的insertBefore方法实现,IE也支持该方法。


<p></p>

<script>

var Div=document.getElementById(/"p1/");

var Element=document.createElement(/"input/");

oElement.type=/"text/";

oDiv.insertBefore(oElement,null);

</script>


6.访问自定义属性

对于IE来说,可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute获取自定义属性。而非IE浏览器只能使用getAttribute获取自定义属性。解决方法是统一通过getAttribute获取自定义属性。

7.input.type属性

在IE中,input.type属性为只读,但在其他浏览器中,input.type属性为读/写。

8.window.location.href

IE支持使用window.location或window.location.href属性,但其他引擎只能使用window.location。解决方法是使用window.location来代替window.location.href。

9.模态窗口和非模态窗口

IE可以通过showModalDialog和showModelessDialog来分别打开模态窗口和非模态窗口,其他引擎则不能。解决方法是直接使用window.open(pageURL,name,parameters)方式打开新窗口。要将子窗口中的参数传递回父窗口,可以在子窗口中使用window.opener来访问父窗口。例如:


var parWin=window.opener;

parWin.document.getElementById(/"Aqing/").;


10.frame

以下面的frame为例。


<frame src=/"xxx.html/"id=/"frameId/"name=/"frameName/"/>


(1)访问frame对象

IE使用window.frameId或window.frameName访问这个frame对象,其他引擎只能使用window.frameName访问这个frame对象。另外,所有引擎都可以使用window.document.getElementById(/"frameId/")来访问这个frame对象。

(2)切换frame内容

所有引擎都可以使用如下代码来切换frame内容。


window.document.getElementById(/"testFrame/").src=/"xxx.html/";



window.frameName.location=/"xxx.html/";


如果需要将frame中的参数传回父窗口,可以在frme中使用parent来访问父窗口,例如:


parent.document.form1.filename.;


如果在<frame>标签中设置如下属性:


<frame src=/"xx.htm/"id=/"frameId/"name=/"frameName/"/>


那么IE可以通过id或name访问该frame对应的window对象,其他引擎只能够通过name来访问该frame对应的window对象。

如果将上述<frame>标签写在顶层窗口的HTML中,那么IE可以使用window.top.frameId或window.top.frameName访问该window对象,其他引擎只能使用window.top.frameName访问该window对象。不过,所有引擎都可以使用window.top.document.getElementById(/"frameId/")访问<frame>标签。

11.body

在IE中,当<body>标签被浏览器完全读入之后,body对象才存在,而其他引擎的body对象,在<body>标签没有被浏览器完全读入之前就已存在。例如:

(1)非IE引擎


<body>

<script>

document.body.onclick=function(evt){

evt=evt||window.event;

alert(evt);

}

</script>

</body>


(2)兼容性用法


<body></body>

<script type=/"text/javascript/">

document.body.onclick=function(evt){

evt=evt||window.event;

alert(evt);

}

</script>


12.访问父节点

对于父元素(parentElement),IE与其他引擎的访问方法是不同的。

❑IE:obj.parentElement

❑Firefox:obj.parentNode

由于所有引擎都支持DOM,因此可以使用obj.parentNode兼容不同浏览器。

13.插入文本

IE支持使用innerText属性为DOM元素插入文本,但其他引擎不支持这个属性,却支持textContent属性。因此,解决方法如下:


if(navigator.appName.indexOf(/"Explorer/")>-1){

document.getElementById(/'element/').innerText=/"my text/";

}else{

document.getElementById(/'element/').textContent=/"my text/";

}


14.文本操作

不同浏览器对于<table>标签的操作各不相同。IE不允许对table和tr对象的innerHTML赋值,也不支持使用appendChild方法添加tr对象。解决方法就是为table追加一个空行。


var row=otable.insertRow(-1);

var cell=document.createElement(/"td/");

cell.innerHTML=/"/";

cell.className=/"className/";

row.appendChild(cell);