js for循环,为什么一定要加var定义i变量

所属分类: 网络编程 / JavaScript 阅读数: 295
收藏 0 赞 0 分享
譬如下面。
复制代码 代码如下:

for(i=0;i<10;i++){//就不写成: var i=0
   alert(i);
}

  但是,这真的不是个好习惯,下面我就说说为什么写Js的for循环一定要加var,否则会时不时给你带来烦人难查的bug。
  譬如现在我们要实现这样的功能:输出  
  10
  20
  30
  40
  50
  60
  70
  80
  90
  100
  通过下面code实现,WriteNumber从1到10循环,每次循环调用TenTimes方法返回10倍的索引值。 
复制代码 代码如下:

<script type="text/javascript">
function WriteNumber() {
for (i = 1; i <= 10; i++) {
document.write(TenTimes(i) + "<br/>")
}
}
function TenTimes(v) {
var result = 0;
alert(i);
for (i = 1; i <= 10; i++) {
result += v;
}
return result;
}
WriteNumber();
//alert(i)
</script>

  你会发现最终只输出了10。大家可以用下面的代码框运行测试。

关于在WriteNumber和TenTimes方法里加不加var,就是说是否声明索引变量i有4种情况:
  第一种情况,WriteNumber和TenTimes各有1个for循环,2个循环里均没有用var声明i索引变量。
  运行结果:会alert出1。结果只输出了10,不是我们所想要的。
  分析:执行WriteNumber时,其作用域内并没有找到声明过的变量i,直接对i进行赋值,则隐式的将i声明为全局变量,(对于函数内部未声明过的变量,如果给它赋值,会隐式的将它声明为全局变量。) 循环开始,i=1,调TenTimes方法,发现TenTimes方法也没有声明过变量i ,所以TenTimes里的i就是全局变量i,就和WriteNumber的i成了同一个。 这时line9 alert出来的自然是1了。TenTimes循环了10次,使得全局的i变成了11,自然WriteNumber就不会执行第2次循环操作了。
  验证:如果在WriteNumber();语句后加alert(i),即取消line16的注释,会发现alert出12(12=10+2个i++),证明了i此时为windows对象。
  第二种情况,WriteNumber声明了i变量,即line3: var i=1,TenTimes未声明i变量,即line10: i=1。
  运行结果:line9 alert(i)处报i未定义错误 ,因为WriteNumber有声明过变量i,所以没有成为全局的i,TenTimes执行时又没有声明过i,所以报未定义。若注释掉line9,输出结果正确。因为当TenTimes里运行到i=1时,隐式将i声明是全局变量,不影响WriteNumber里的i。WriteNumber仍然会执行10次循环。
  验证:如果在WriteNumber();语句后加alert(i),即取消line16的注释,会发现alert出11(11=10+TenTimes里的i++),证明了此时有windows.i。
  第三种情况,WriteNumber没有声明i变量,即line3: i=1,TenTimes声明了i变量,即line10: var i=1。
  运行结果:弹出10个undefined。因为WriteNumber未声明i,隐式将i声明是全局变量,而TenTimes有声明过变量i(补充一句,对于变量的声明都是在预编译中进行的),所以line9 alert(i)里的i不是windows.i,而是TenTimes声明的变量i,此时当然是undefined了。同时,发现输出结果正确,因为TenTimes的i不会影响WriteNumber的全局i,WriteNumber仍然是执行了10次循环。
  第四种情况:WriteNumber和TenTimes均用var声明了i。
  运行结果:注释掉line9,不说了,好习惯,结果当然完美。
  虽然第二、三种情况输出结果是正确的,但是对i的使用很混乱,应该算是运气导致结果正确,因为刚好1个是window.i,一个是函数内部的私有变量i,使得没有冲突。
此文虽然讲的是写for循环为什么一定要加var,但其实讲的是变量的作用域(或者说变量的生命周期)。理解之后,下面的2段code运行结果你应该能准确说出答案吧。


Ps:说道coding的好习惯,想起了这个:if(a==3) 应该写成if(3==a) 。因为我们常会把==写成1个=,如果把变量写在右边时只写了1个=,就会报编译错误,这样就能及时发现错误。
更多精彩内容其他人还在看

js实现图片上传预览原理分析

这篇文章主要为大家详细介绍了js实现图片上传预览的原理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Angular限制input框输入金额(是小数的话只保留两位小数点)

最近做项目遇到这样的需求输入框要求输入金额,只能输入数字,可以是小数,必须保留小数点后两位。下面分为两部分代码给大家介绍实现代码,需要的的朋友参考下吧
收藏 0 赞 0 分享

详解vue-cli + webpack 多页面实例配置优化方法

本篇文章主要介绍了详解vue-cli + webpack 多页面实例配置优化方法,具有一定的参考价值,有兴趣的可以了解一下
收藏 0 赞 0 分享

详解React-Native解决键盘遮挡问题(Keyboard遮挡问题)

本篇文章主要介绍了React-Native解决键盘遮挡问题(Keyboard遮挡问题),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

JavaScript反弹动画效果的实现代码

本文通过实例代码给大家介绍了js反弹动画效果的实现代码,需要的朋友参考下吧
收藏 0 赞 0 分享

解决vue2.x中数据渲染以及vuex缓存的问题

本篇文章主要介绍了vue2.x中请求之前数据显示以及vuex缓存的问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

jsonp跨域请求详解

这篇文章主要为大家详细介绍了jsonp跨域请求的相关资料,激活了所有接口支持浏览器跨域请求的封装,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

解决vue里碰到 $refs 的问题的方法

本篇文章主要介绍了解决vue里碰到 $refs 的问题的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

js自定义弹框插件的封装

这篇文章主要为大家详细介绍了js自定义弹框插件的简单封装,自己封装一个弹框插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

深入理解vue $refs的基本用法

本篇文章主要介绍了深入理解vue $refs的基本用法 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享
查看更多