JavaScript的陷阱(3)
作者:秦歌 来源:随网之舞 时间:2008-10-28 19:52:00
‘this’
另一个常见的错误是忘记使用“this”。在JavaScript对象中定义的函数访问这个对象的属性,但没有使用引用标识符“this”。例如,下面是错误的:
function myFunction() { var myObject = { objProperty: "some text", objMethod: function() { alert(objProperty); } }; myObject.objMethod();} function myFunction() { var myObject = { objProperty: "some text", objMethod: function() { alert(this.objProperty); } }; myObject.objMethod();}
有一篇A List Apart文章用通俗易懂的英文表达了this绑定的问题。
对this使用最大的陷阱是this在使用过程中其引用会发生改变:
<input type="button" value="Gotcha!" id="MyButton"><script>var MyObject = function () { this.alertMessage = "Javascript rules"; this.ClickHandler = function() {alert(this.alertMessage ); }}();document.getElementById(”theText”).onclick = MyObject.ClickHandler</script>
其解决方案是:
var MyObject = function () {var self = this;this.alertMessage = “Javascript rules”; this.OnClick = function() { alert(self.value); }}();
类似问题的更多细节和解决方案请看《JavaScript作用域的问题》。
遗漏的参数
当给函数增加一个参数时,一个常见的错误是忘记更新这个函数的所有调用。如果你需要在已经被调用的函数中增加一个参数来处理一个特殊情况下的调用,请给这个函数中的这个参数设置默认值,以防万一在众多脚本中的众多调用中的一个忘记更新。
function addressFunction(address, city, state, country){ country = country || “US”; span>//剩下代码}
你也能通过获取arguments来解决。但是在这篇文章我们的注意力在陷阱上。同时在《Javascript风格要素(2)》也介绍了||巧妙应用。
for关键字
在JavaScript中关键字for有两种使用方式,一个是for语句,一个是for/in语句。for/in语句将遍历所有的对象属性(attribute),包括方法和属性(property)。决不能使用for/in来遍历数组:仅在当需要遍历对象属性和方法时才使用for/in。
for(var myVar in myObject)语句用一个指定变量无任何规律地遍历对象的所有属性。如果for/in循环的主体删除了一个还没有枚举出的属性,那么该属性就不在枚举。如果循环主体定义了新属性,那么循环是否枚举该属性则是由JavaScript的实现决定。
for(var 1=0; i < myArray.length; i++)语句会遍历完一个数组的所有元素。
为了解决这个问题,大体上你可以对对象使用 for … in,对数组使用for循环:
listItems = document.getElementsByTagName('li');for (var listitem in listItems){ }for ( var i = 0; i < listItems.length; i++) { //这是真正你想要的}
对象的有些属性以相同的方式标记成只读的、永久的或不可列举的,这些属性for/in无法枚举。实际上,for/in循环
会遍历所有对象的所有可能属性,包括函数和原型中的属性。所有修改原型属性可能对for/in循环带来致命的危害,所以需要采用hasOwnProperty和typeof做一些必要的过滤,最好是用for来代替for/in。
switch语句
Estelle Weyl写了一篇switch statement quirks,其要点是:
没有数据类型转换
一个匹配,所有的表达式都将执行直到后面的break或return语句执行
你可以对一个单独语句块使用多个case从句
undefined ≠ null
null是一个对象,undefined是一个属性、方法或变量。存在null是因为对象被定义。如果对象没有被定义,而测试它是否是null,但因为没有被定义,它无法测试到,而且会抛出错误。
if(myObject !== null && typeof(myObject) !== 'undefined') { }if(typeof(myObject) !== 'undefined' && myObject !== null) { }
Harish Mallipeddi对undefined和null有一个说明。
事件处理陷阱
刚接触事件处理时最常见的写法就是类似:
window.onclick = MyOnClickMethod
这种做法不仅非常容易出现后面的window.onclick事件覆盖掉前面的事件,还可能导致大名顶顶的IE内存泄露问题。为了解决类似问题,4年前Simon Willison就写出了很流行的addLoadEvent():
function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; }else { window.onload = function() { oldonload(); unc(); } }}addEvent(window,'load',func1,false);addEvent(window,'load',func2,false);addEvent(window,'load',func3,false);
当然在JavaScript库盛行的现在,使用封装好的事件处理机制是一个很好的选择,比如在YUI中就可以这样写:
YAHOO.util.Event.addListener(window, "click", MyOnClickMethod);