应当避免的JavaScript编程问题

来源:互联网 发布:阿里云短信发送api 编辑:程序博客网 时间:2024/06/05 02:03

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


等价比较(Equality Operator) 

JavaScript中有两个相等比较操作符.第一个就是两个等于号(==),它只比较值是否相等,而不关心数据类型。例如,当比较1true,结果为true.

if(1==true){

    //这部分代码会被运行

}

以下是几个不同的例子.

1 == "1"        //true"true" == true  //false1 == 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       //false1===true      //false"true"===true //false


不为引用类型赋NULL

当引用类型变量(object or Array)不再使用时,没有给它赋NULL是一个常见的错误.看看下面的例子:

var arr=[1,2,3]; //执行一些操作 //当不再使用时,赋NULLarr =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错误


原创粉丝点击