<input type="button" value="Gotcha!" id="MyButton">
<script>
var MyObject = function () {
this.alertMessage = "Javascript rules";
this.ClickHandler = function() {
alert(this.alertMessage );
//返回结果不是”JavaScript rules”,执行MyObject.ClickHandler时,
//this的引用实际上指向的是document.getElementById("theText")的引用
}
}();
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”; //如果没有传入country,假设 “US”
span>//剩下代码
}
你也能通过获取arguments来解决。但是在这篇文章我们的注意力在陷阱上。同时在《Javascript风格要素(2)》也介绍了||巧妙应用。
for语句
在JavaScript中“for”循环将遍历所有的对象属性(attribute),包括方法和属性(property)。决不能使用for in来遍历数组:仅在当需要遍历对象属性和方法时才使用for in。
1. for(var myVar in myObject)用一个指定变量无任何规律地遍历对象的所有属性。如果for/in循环的主体删除了一个还没有枚举出的属性,那么该属性就不在枚举。如果循环主体定义了新属性,那么循环是否枚举该属性则是由JavaScript的实现决定。
2. for(var 1=0; i < myArray.length; i++)会遍历完一个数组的所有元素。
为了解决这个问题,大体上你可以对对象使用 for … in,对数组使用for循环:
listItems = document.getElementsByTagName('li');
for (var listitem in listItems){
//这里将遍历这个对象的所有属性和方法,包括原生的方法和属性,但不遍历这个数组:出错了!
}
//因为你要循环的是数组对象,所用for循环
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 ,其要点是:
1. 没有数据类型转换
2. 一个匹配,所有的表达式都将执行直到后面的break或return语句执行
3. 你可以对一个单独语句块使用多个case从句
undefined ≠ null
null是一个对象,undefined是一个属性、方法或变量。存在null是因为对象被定义。如果对象没有被定义,而测试它是否是null,但因为没有被定义,它无法测试到,而且会抛出错误。
if(myObject !== null && typeof(myObject) !== 'undefined') {
//如果myObject是undefined,它不能测试是否为null,而且还会抛出错误
}
if(typeof(myObject) !== 'undefined' && myObject !== null) {
//处理myObject的代码
}
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);