块级绑定(var、let、const的区别)
当学习ES6之后,发现之前使用的var声明方式确实存在许多缺点,我们可以有更好的选择
一、var声明的缺陷
1.允许重复的变量声明。
我们以前通常是这么声明变量的 var a = 0
我们都知道这样声明可以重复,比如var a = 0;var a = 1;
这样是没问题的,后面的会覆盖前面的,恰恰因为这,试想一下我们如果在开头就var了一个a,隔了一千行之后忘记了前面还有个a又var了一个,这时候第一个a的类型、值之类的都被覆盖掉了,有时候类型相同甚至不会报错,找起bug来很是困扰
2.变量提升,访问怪异。
我们来看一段代码
if (Math.random() < 0.5) {
var a = "abc";
console.log(a);
}
else {
console.log(a);
}
console.log(a);
我们来读一下这段代码,从格式上来理解是,当条件满足时,声明变量a并输出a,当不满足时输出a,那么当条件不满足时a应该还没声明才对,这时候输出a应该会报错才是理所应当的,但是js并没有报错,因为var a被提升了,提升后就变成了我先声明了一个a,条件成立赋值并输出,else直接输出,与代码的字面格式意思就不一样了,这就是变量提升带来的怪异之处。
3.变量提升,闭包问题。
接着我们继续看一段代码
var div = document.getElementsByTagName("divButtons")
for (var i = 0; i < 10; i++) {
div[i].onclick = function () {
console.log(i); //输出10
}
}
// 循环结束后,i:10
这应该是学闭包时小伙伴们都会见过的例子,十个div本来我们是想让它们点击时分别输出各自的编号,结果到头来全部输出了一样的数字10,这就是闭包的典型例子,那这个例子跟var有什么关系呢?其实还是变量提升的问题。理想状态是一个div对应一个i,但是当var i 提升之后,就变成了
var i = 0;
for(;i<10;i++)
可以看到i被提升到了最上面之后,循环只是给同一个i不断地赋值罢了,当点击事件发生,去输出i的时候,输出的就是同一个i,且这个i在不断赋值之后变成了10,这就是变量提升带来的闭包问题。
4.污染全局变量
var声明还有个小问题就是污染全局变量
//假设我们
var a = 10;
//那输出就有两种方式
console.log(a);
console.log(window.a);
通过var声明的变量是可以使用window来访问的,也就是说变量被挂载到全局对象上了,那么就很有可能会覆盖掉本来就内置的全局对象成员,举个例子
var alert = 'a';
window.alert('b');
本来window.alert方法是弹出一个弹框,但如果var声明了一个alert,就会发现window下面的alert方法被覆盖了,再想向常规那样的调用就会报错。
未完待续