1 命名函数的赋值表达式
将命名函数赋值给一个变量。
var foo = function ss() {
ss();//正常运行
}
ss();//出错
ss函数声明外是不可见的,这是因为我们已经把函数赋值给了 foo
; 然而在ss 内部依然可见。这是由于JavaScript
的命名处理所致, 函数名在函数内总是可见的。
注意:在IE8及IE8以下
版本浏览器ss在外部也是可见的,是因为浏览器对命名函数赋值表达式进行了错误的解析, 解析成两个函数 foo和ss。
2 方法的赋值表达式
将一个方法赋值给一个变量。
var ss = someObject.methodTest;
ss();
ss
就像一个普通的函数被调用;因此,函数内的 this
将不再被指向到 someObject
对象。而是指向了window
。
3 循环中的闭包
比较常见的错误出现在循环中使用闭包。
for(var i = 0 ; i < 55 ; i++){
setTimeout(function () {
console.log("我不做人了,jojo");
},1000);
}
上面的代码会输出文字55次。
当 console.log
被调用的时候,匿名函数保持对外部变量i的引用,此时 for循环已经结束,i的值被修改成了55。为了得到想要的结果,需要在每次循环中创建变量i
的拷贝。为了避免引用错误,为了正确的获得循环序号,最好使用 匿名包装器(注:其实就是我们通常说的自执行匿名函数)。
3.argument对象
JavaScript 中每个函数内都能访问一个特别变量 arguments
。这个变量维护着所有传递到这个函数中的参数列表。arguments变量不是一个数组
(Array)。 尽管在语法上它有数组相关的属性 length
,但它不从 Array.prototype
继承,实际上它是一个对象(object)。
因此,无法对 arguments
变量使用标准的数组方法,比如 push
, pop
或者 slic
e。 虽然使用 for
循环遍历也是可以的,但是为了更好的使用数组方法,最好把它转化为一个真正的数组。
转化为数组:
创建一个新的数组,包含所有 arguments
对象中的元素。Array.prototype.slice.call(arguments); arguments
对象为其内部属性以及函数形式参数创建 getter
和 setter
方法。因此,改变形参的值会影响到 arguments 对象的值,反之亦然。
function ss(a,b,c){
arguments[0] = 2;
a;//2
b = 4;
arguments[1];//4
var d = c;
d = 9;
c;//3
}
ss(1,2,3);
4 定时器
手动清理定时器。
var jojo = setTimeout(ss,1000);
clearTimeout(jojo);
清除所有定时器。由于没有内置的清除所有定时器的方法,可以采用一种暴力的方式来达到这一目的。
for(var i = 0 ;i < 1000 ; i++){
clearTimeout(i);
}
可能还有些定时器不会在上面代码中被清除(注:如果定时器调用时返回的 ID 值大于 1000), 因此我们可以事先保存所有的定时器 ID,然后一把清除。建议不要在调用定时器函数时,为了向回调函数传递参数而使用字符串的形式。
function ss(a,b,c) {}
setTimeout('ss(1,2,3)',1000);//尽量不要这么做
//可以使用匿名函数完成相同的功能
setTimeout(
function() {
ss(1,2,3);
}
,1000)
绝对不要使用字符串作为 setTimeout
或者 setInterval
的第一个参数, 这么写的代码明显质量很差。当需要向回调函数传递参数时,可以创建一个匿名函数,在函数内执行真实的回调函数。避免使用 setInterval,因为它的定时执行不会被 JavaScript 阻塞。