应当避免的JavaScript编程问题

如果刚开始学习JavaScript无论完全自己写程序,或者使用一些框架 (jQuery, Mootools, Dojo, YUI) ,下面这几个错误你必须要避免, 它们都是我学习JavaScript的经验之谈。


等价比较(Equality Operator) 

JavaScript中有两个相等比较操作符.第一个就是两个等于号(==),它只比较值是否相等,而不关心数据类型。例如,当比较1true,结果为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垃圾回收( garbage collector )算法的引擎, 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号它们都被清空了,但这个语句的问题是同时把arr1arr2都指向了相同的数组,而不再是之前各自独立的数组.  所以改变其中一个就也自动体现到另一个.

在第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.csdn.net/horkychen

原文地址:http://www.ifadey.com/2011/05/javascript-mistakes-you-must-avoid/


Reference:你可能会犯的11个JavaScript错误


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值