一道笔试题( 网易2017校招内推笔试)
现有如下html结构:
<ul>
<li>click me</li>
<li>click me</li>
<li>click me</li>
<li>click me</li>
</ul>
运行如下代码:
window.onload=function(){
var elements=document.getElementsByTagName('li');
var length=elements.length;
for(var i=0;i<length;i++){
elements[i].onclick=function(){
alert(i);
}
}
依次点击4个li标签,哪一个选项是正确的运行结果( 依次弹出4,4,4,4 )
其中原理理解
- 在以上代码中出现闭包,高程第三版提到:
闭包只能取得包含函数中任何变量的最后一个值
,几乎可以直接确定答案。 -
底层的原理:
-
首先在x 行补齐函数
-
在chrome下进入调试,首先执行的是chrome的include.preload.js中的checkCollapse()函数,之后进入window.onload函数
-
此时变量初始化(声明提升),
i==element==length==undefined
-
运行到for之前,
i==undefined,length=4,element:htmlcollection[4]
; -
进入for循环后,i 从 0 循环至 4 停止,
-
当
i ==0
时,element[0]
的onclick
由null
变为function(){alert(i);}
,element[1]
、element[2]
和element[3]
依旧为null- 这里应关注两点:1:该函数的
prototype
为Object
; -
2:函数的`scope`中的`Closure`中存储着变量`i`,此时值为:`0`;
- 这里应关注两点:1:该函数的
-
当
i ==1
时,element[1]
的onclick
由null
变为function(){alert(i);}
,element[2]
和element[3]
依旧为null- 注意: 1:函数的
scope
中的Closure
中存储着变量i
,此时值为:1
; -
2:当i==1时,element[0]的`scope`中的`Closure`的 i 已经变为 1;
- 注意: 1:函数的
-
当
i ==2
时,element[2]
的onclick
由null
变为function(){alert(i);}
,element[3]
依旧为null- 注意: 1:函数的
scope
中的Closure
中存储着变量i
,此时值为:2
; -
2:当i==2时,element[1]和element[0]的`scope`中的`Closure`的 i 已经变为 2;
- 注意: 1:函数的
-
当
i ==3
时,element[3]
的onclick
由null
变为function(){alert(i);}
- 注意: 1:该函数的
prototype
为Object
; -
2:当i==3时,element[2]、element[1]和element[0]的`scope`中的`Closure`的 i 已经变为 3;
- 注意: 1:该函数的
-
当
i==4
时,跳出循环。
-
-
可以看出来,for内中的
匿名函数
的作用域的最前端的变量对象是匿名函数自己的执行环境的变量对象,紧接着的变量对象是外层函数执行环境的变量对象,for内部所有的匿名函数共享了外层函数的执行变量,所以匿名函数在由事件触发时被执行,访问的是外层 函数 中 的i
(由作用域链搜索得到), -
所以在以上结果中事件触发后弹出的是最终的 i 值为 4 .
-