for循环的这2种写法为什么显示的结果却不一样

demo的目的是把浮动布局的li在js里转成绝对定位。但关于for循环的写法,本来是第一种写法,没有问题。想给优化一些,就改成一个for循环,但却布局显示错误。请问为什么第二种写法是错的?

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
*{margin: 0;padding: 0;}
 ul{list-style: none;}
 #ul1{width: 330px;height:330px;margin: 0 auto;position: relative;border: 1px solid #000;}
 li{width: 100px;height: 100px;background-color: red;float: left;margin: 10px 0 0 10px;}
</style>
</head>
<body>
    <ul id="ul1">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</body>
<script>
var ul1=document.getElementById('ul1');
var ali=ul1.getElementsByTagName('li');
var arr=[];
<!-- 第一种写法开始(正常显示) -->
<!-- for (var i = 0; i < ali.length; i++) {
    arr.push({left:ali[i].offsetLeft,top:ali[i].offsetTop});
}
for (var i = 0; i < ali.length; i++) {
    ali[i].style.position='absolute';
    ali[i].style.left=arr[i].left+'px';
    ali[i].style.top=arr[i].top+'px';
    ali[i].style.margin='0px';
}-->
<!-- 第一种写法结束 -->

<!-- 第二种写法开始(不正常显示) -->
for (var i = 0; i < ali.length; i++) {
    arr.push({left:ali[i].offsetLeft,top:ali[i].offsetTop});
    ali[i].style.position='absolute';
    ali[i].style.left=arr[i].left+'px';
    ali[i].style.top=arr[i].top+'px';
    ali[i].style.margin='0px';
}
</script> 
</html>
阅读 3.1k
4 个回答

因为楼楼原来的li是左浮动的,
for循环中li是一个个被赋予了absolute定位。
当第一个li被赋予absolute定位时候,它会移动到第一个块的位置,也就是left和top都是10px,因为第一个li脱离了,所以后面的也自然补上了,所以这个时候第二个li就也会出现在left和top是10px的地方,同样后面的也前移动了。很巧合,以此类推,结果一不小心就都取到了left和top是10px,也就都凑在一起了。

刚刚测试第二种写法,console.log(arr[i]);输出的值全部相同。想起这个demo的视频里老师说的话。在同一代码块中,ali[i].style.position='absolute';即使写在下面,执行的顺序也是比有些代码要提前。即每次循环都是行ali[i].style.position='absolute';,这样一来,每个li的left值和top值都是10,所以再执行arr.push({left:ali[i].offsetLeft,top:ali[i].offsetTop});时获取到的也都是一样的。
本来是觉得视频里老师这种分代码块的写法有点费事,自己改用其他方法重写案例,结果还是有这个分代码块的问题。
受了楼上的回答的提示,总算明白怎么回事了。

新手上路,请多包涵

ali[i].offsetLeft 这种写法是很菜的写法,因为这样会让浏览器强制刷新重排缓冲区,从而多次触发重排。
建议使用一个class控制下面li的属性一次性添加,JS添加class完成效果

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题