最近在读大叔译的javascript编程精解这本书,确实是本好书,大爱。
以前对javascript某些概念迷迷糊糊,虽然知道怎么回事,但一直弄不明白其中的原因...
那么就先拿以前一直弄不明白的这道题讲讲吧,如下:
例1:
<
a
href
="javascript:;"
>点我
</
a
> /
<
a
href
="javascript:;"
>点我
</
a
> /
<
a
href
="javascript:;"
>点我
</
a
>
<
script
type
="text/javascript"
>
var
atags
=
document.getElementsByTagName(
'
a
'
);
for
(
var
i
=
0
, max
=
atags.length; i
<
max; i
++
) {
atags[i].onclick
=
function
() {
alert(i);
}
}
</
script
>
预期结果可能是想弹出 0,1,2。可惜的是都弹出了:3
如果你一搜,一般会有这样的解决办法,如下面:
例2:
<
script
type
="text/javascript"
>
var
atags
=
document.getElementsByTagName(
'
a
'
);
for
(
var
i
=
0
, max
=
atags.length; i
<
max; i
++
) {
(
function
(index) {
atags[i].onclick
=
function
() {
alert(index);
}
})(i);
}
</
script
>
分析下两个例子的运行情况,首先了解一下javascript的几个知识点:
1、作用域
2、闭包
3、自执行函数。
4、值类型和引用类型
我来引用一下最近读这本书的几句精解:
1、JavaScript唯一能创建新作用域的地方是 function
2、包裹一些局部变量的一个函数叫做一个闭包
3、自执行函数表达式这个大家应该都很清楚了,不清楚就去看下大叔的:即调用的函数表达式
4、这个也应该清楚吧,我说下吧:Number Boolean String 在 js 里属于值类型,对像属于引用类型,如下例:
<
script
type
="text/javascript"
>
function
changeValue(value) {
value
=
5
;
}
function
changeObj(objValue) {
objValue.i
=
5
;
}
var
i
=
0
;
var
obj
=
{ i:
0
};
changeValue(i);
changeObj(obj);
alert(i);
//
0
alert(obj.i);
//
5
</
script
>
到这里,上面的几个知识点,应该都比较清楚了。
先来看作用域:JavaScript唯一能创建新作用域的地方是 function,那么就是说像 for 这类的是不会产生自己的作用域的。我们来实验一下。
for (var i = 0; i
<
5
; i++) {
//这里干点啥
}
alert(i); //5
可以看出,for里的定义确实不会产生自己的作用域,这个其实也就是在全局里定义了一个变量i,就像以下这样:
var i = 0;
for (; i
<
5
; i++) {
}
alert(i); //5
贴心提示:从上面的例子我们能看出,一定要理解作用域,否则很容易发生冲突。比如:
//a某在这写了个变量 i
var i = 9527;
//b某在这写了这货
for (var i = 0; i
<
5
; i++) {
//
}
//a某在这果断悲剧了。
alert(i);
那么我们再来看上面的例1,这时我们应该很清楚为什么会全部弹出:3了。
因为所有链接弹出的是全局变量i,而全局变量i在循环完后的值是3,如下:
<
script
type
="text/javascript"
>
var
atags
=
document.getElementsByTagName(
'
a
'
);
for
(
var
i
=
0
, max
=
atags.length; i
<
max; i
++
) {
atags[i].onclick
=
function
() {
alert(i);
}
}
alert(i);
//
这里显示:3
</
script
>
例2:这里如果理解上面的一些知识,例2也就不难理解了。
匿名自执行函数表达式收到index,因为是值类型参数,所以匿名函数内部重新分配这个局部变量。
然后链接 onclick 绑定的那个事件函数就是匿名函数的内部函数,并引用了匿名函数的那个局部变量(index)(这里是产生了一个闭包的)
最后的结果就是三个链接分别显示了三个匿名函数的局部变量。
[注:这里感谢 @Justany_WhiteSnow 的指点,原先我认为例2没有产生闭包,我说错了,差点误导大家,这里及时做个修改吧。并且把 @Justany_WhiteSnow 的正确见解在这里与大家分享下。]
另外我们还可以把那个自执行函数拿到外面:
<
script
type
="text/javascript"
>
function
bind(index) {
atags[index].onclick
=
function
() {
alert(index);
}
}
var
atags
=
document.getElementsByTagName(
'
a
'
);
for
(
var
i
=
0
, max
=
atags.length; i
<
max; i
++
) {
bind(i);
}
</
script
>
好,这篇就到这了,有什么说错的地方欢迎大家指正。
转载请注明出处,谢谢。