如果刚开始学习JavaScript,无论完全自己写程序,或者使用一些框架 (jQuery, Mootools, Dojo, YUI) ,下面这几个错误你必须要避免, 它们都是我学习JavaScript的经验之谈。
等价比较(Equality Operator)
JavaScript中有两个相等比较操作符.第一个就是两个等于号(==),它只比较值是否相等,而不关心数据类型。例如,当比较1和true时,结果为true.
if(1==true){
//这部分代码会被运行
}
以下是几个不同的例子.
1 == "1" //true
"true" == true //false
1 == true //true
"0" == 0 //true
"" == 0 //true
" " == 0 //true
"Str" == false //false
"Str" == true //false
如果不了解javaScript的==操作符,其中一些结果可能有点出乎意料.事实上它们都被转换成Number类型进行比较的.
比如第一个例子 (1== “1″).左边已经是一个数值了,不需要转换.右边是一个字串,它会被转为数值1.
第二个例子(“true”== true)结果为false是因为字串包含的是字符,而不是数字符号,它会被转为NaN,表示Not a Number. 任何值同NaN相比,结果就是false.
可以使用Number构造函数来检查转换的结果。下面是使用FireBug测试的结果.
三个等于号的全等比较符,除了比较值之外,还会比较数据类型.如果数据类型也不同,结果就是false.只有当数据类型和值都相同时结果才为true.
4===4 //true
"2"===2 //false
1===true //false
"true"===true //false
不为引用类型赋NULL
当引用类型变量(object or Array)不再使用时,没有给它赋NULL是一个常见的错误.看看下面的例子:
var arr=[1,2,3];
//执行一些操作
//当不再使用时,赋NULL
arr =null;
这样做最大的好处就是可以让JavaScript引擎的垃圾回收器可以及时释放被占用的内存.如果变量的作用域近似于全局变量,及时赋NULL就很重要了.局部变量会在离开作用域时被自动解构(特别是使用Mark and Sweep垃圾回收(garbagecollector )算法的引擎, WebKit使用的就是这种算法.).
引用类型变量的初始化 (Reference Variable Initialization)
永远不要在单行赋值语句中为多个引用类型变量(object and array)赋值.用下面的例子可以更好地理解.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var arr1=[1,2,3] , arr2=['a','b','c'];
//重置两个数组 arr1 = arr2=[]; //为两个数组各增加一项 arr2.push(32); arr1.push(10);
//输出看到相同的结果//OUTPUT: 10, 32 alert( arr1.join()); alert( arr2.join()); |
第1行和第2行分别创建了两个数组.然后在第5号它们都被清空了,但这个语句的问题是同时把arr1和arr2都指向了相同的数组,而不再是之前各自独立的数组. 所以改变其中一个就也自动体现到另一个.
在第8行为arr2增加了32,在第9行,为arr1增加了一个10.通过检查13行和14行的输出结果可以看到两个数组有相同的内容.
不要忘记使用var
在JavaScript中,可以使用var定义变量, 但是也可以不使用var直接定义. 这两种方式有很大的不同.看看下面的例子:
function createVar(){
var myVar='local';
};
alert( myVar );//输出:undefined
上面例子中有一个使用var定义的变量myVar, 它在函数外就无法访问了.下面的例子将不使用var定义变量.
function createVar(){
myVar ='local';
};
alert( myVar );//输出:local
可以看到不使用var定义的变量myVar在全局作用域也可以访问. 换句话说var定义的是局部变量.在JavaScript声明变量一定要小心,尽量在使用它们前用var来声明.
没有使用事件代理 (Not Using Event Delegation)
JavaScrip中加入(attach)一个事件处理程序很容易.下面的例子就为指定ID的元件指定了一个click事件处理程序.
document.getElementById('myLink').addEventListener('click',function(){
//you code goes here...},false);
假设你要为所有的td元件增加一个click事件处理程序.需要为表中的每个td项写一个处理程序吗?
<table id="myTable">
<tbody>
<tr>
<td>1, 1</td>
<td>1, 2</td>
</tr>
<tr>
<td>2, 1</td>
<td>2, 2</td>
</tr>
</tbody>
</table>
事件代理程序可以简化这件事.为整个表myTable指定一个clikc事件处理程序,然后在其内容检查是不是某个td被点击了.这样就不需要为每个td项指定事件处理程序了, 这样的程序就是所谓的事件代理.下面是它的代码:
document.getElementById( 'myTable' ).addEventListener( 'click', function( e ) {
if( e.target && e.target.nodeName == 'TD' ) {
console.log( e.target.innerHTML );
//to access id
//console.log( e.target.id );
//to access className
//console.log( e.target.className );
}
}, false );
innerText与 innerHTML
JavaScript开发的新丁常常会搞混innerText和innerHTML.它们都由DOM元件调用. innerHTML将取得元件内部的HTML代码,而innerText只是取得元件中的文本内容.
Html中的黑色的部分将是innerHTML属性的输出结果.其中HTML标签<p>也被输出了.
再来看一个innerText的例子.
可以看到innerText只取得了文本内容,而没有HTML标签..
批量添加节点(Adding Nodes in Bulk)
为DOM元件添加一系列节点是比较普遍的.比如将Ajax调用返回的名字列表加入到ul元件中.下面是一种做法:
window.onload = function() {
//ul element - <ul id="list"></ul>
var list = document.getElementById( 'list' );
var item = null;
//假设调用Ajax返回的是json数据
var ajaxResponse = [
{ 'name' : 'Haiku' },
{ 'name' : 'Linux' },
{ 'name' : 'OS X' },
{ 'name' : 'Windows' }
];
//添加名字列表到document中
for( var i in ajaxResponse ) {
item = document.createElement( 'li' );
item.appendChild( document.createTextNode( ajaxResponse[ i ].name ) );
list.appendChild( item );
}
} //end onload
/*
..:: 输出 ::..
<ul id="list">
<li>Haiku</li>
<li>Linux</li>
<li>OS X</li>
<li>Windows</li>
</ul>
*/
这个方法的问题是使用for循环添加各项到列表,DOM每次都立即进行更新,这样会降低程序的性能.
“DocumentFragment 是一个轻量级的document,而且不会直接显示在网页上.”
相同的结果也可以使用DocumentFragment达到, 而且只在最后更新到网页,从而不致对网页影响太大.下面就是改写的例子.
window.onload = function() {
//创建DocumentFragment
var documentFragment = document.createDocumentFragment();
var list = document.getElementById( 'list' ); //<ul id="list"></ul>
var item = null;
//假设调用Ajax返回的是json数据
var ajaxResponse = [
{ 'name' : 'Haiku' },
{ 'name' : 'Linux' },
{ 'name' : 'OS X' },
{ 'name' : 'Windows' }
];
//添加所有名字到documentFragment
for( var i in ajaxResponse ) {
item = document.createElement( 'li' );
item.appendChild( document.createTextNode( ajaxResponse[ i ].name ) );
documentFragment.appendChild( item );
}
//将documentFragment加到list中
list.appendChild( documentFragment );}
John Resig有一篇很棒的博客详细解释了DocumentFragment以及它对性能的影响.
使用innerHTML操作DOM (DOM Manipulation using innerHTML)
永远不要对innerHTML使用+=来添加新的标签.无论什么时候修改innerHTML,DOM都会被更新(浏览器需要重新绘制).所以使用+=操作符添加新的标签也会降低性能,在循环里使用将更为严重.
var container = document.getElementById( 'container' );
for( var i = 1; i <= 10; ++i ) {
container.innerHTML += 'Item ' + i + '<br />';}
可以使用一个临时变量来存储要添加的内容. 下面是一个例子:
var container = document.getElementById( 'container' )
, str = '';
for( var i = 1; i <= 10; ++i ) {
str += 'Item ' + i + '<br />';}
container.innerHTML += str;
转载请注明出处:http://blog.youkuaiyun.com/horkychen
原文地址:http://www.ifadey.com/2011/05/javascript-mistakes-you-must-avoid/
Reference:你可能会犯的11个JavaScript错误