最新消息:Rockyxia Web技术博客全新改版,响应式布局满足各种设备各种尺寸的访问需求。

ES6第二节:ES6新增了let关键字,干嘛用的?

ES6 rockyxia 3522浏览

写在前面

大白话,讲编程,连载的第一节,得到大家的认可和赞赏,谢谢支持。文章还出现了几个错别字,惭愧!此外,连载的频率初定为每周2节,时间大约在早上10:00;大家对此有何建议都可以留言,前端君都会回复。来吧,开始本节的学习!

ES6 给开发者带来很多令人激动的特性,其中let关键字就是其中之一。

那么,let关键字是什么东西?

20160620-es6

let 的用途

我们回想一下,我们平时在写代码的时候,用var来声明一个变量,除此之外,好像也没用其他的关键字了,不管我们声明的是字符串类型、数组类型还是数字类型等,都用一个var 搞掂(因为JavaScript拥有动态类型),很方便。但现在,ES6告诉你,除了var,不妨试试用let来声明变量试试看。

咦,这么说,let关键字是用了声明变量的咯?是的,let的用途就是用来声明变量的。

那么,let关键字是什么东西?

好端端的用var声明就可以了,为什么要用新的let关键字来声明啊?难道用var有什么不足的地方吗?是的,还真有。

用 var 的不足之处

不足一

来,我们看一段简短的代码:

var arr = [ ];
for(var i=0;  i<10;  i++){
    arr [i] = function(){
         alert(i)
    }
}
arr [8](); //结果:10

看代码,不难猜测代码的意图是想给数组a的元素赋值,每一个元素是一个函数,运行后弹出相对应的数字,比如:运行arr[8]();想alert出一个数字8,运行arr[1](); 想alert出一个数字1,依次类推。但是结果并不是我们预想的那样。运行后实际弹出的是10;不管你运行的是arr[8]还是arr[5],或者是数组内的其他元素,都是alert出一个数字:10。但这并不是我们想要的(不要说你故意这么写的,就是想弹出10就好了),为什么是10呢(往下读,有解释)?至少目前我们可以知道了这是var不足的地方。

那么let能解决这个问题吗?ES6说:能啊,不信你试试看!

用let替换var后,我们再看看:

var arr = [ ];
for(let i=0;  i<10;  i++){
    arr[i] = function(){
         alert(i)
    }
}
arr[8](); //结果:8

对比一下两段代码,唯一的不同之处就是循环的时候初始化变量 i 是使用let,而不是用var,运行arr[8]()后确实弹出了数字8;如果运行的是arr[3](),就会弹出数字3;这才是我们的本意啊,总算实现了,感谢上帝,感谢ES6,感谢let关键字!

为什么用let就可以,用var就跑偏了呢?这是因为let声明的变量仅仅在自己的块级作用域起作用,出了这个块级作用域就不起作用。就好比,小明在国内考的“高级程序员”证,去到国外应聘,别人就不承认你的文凭了,小明只能乖乖待在国内持证上岗。而let声明的变量也一样,出不了自己的块级作用域。

那么,什么是块级作用域,怎么才算一个块级作用域?

任何一对花括号(这玩意:{ })中的语句都属于一个块,在花括号里面用let定义的所有变量在花括号外都是不可见的,我们称之为块级作用域。

怪不得小明的证件去到美国没法使用了,人家认为它的证件“不可见“,就是没这回事,不承认你的证。回到代码中,for循环含有有{ },也就是含有了块级作用域,每个变量 i 都只是在自己的作用域起作用,例如:第10次循环中的 i 的值不会影响到到第9次循环。

如果用var声明的变量,就不是这种情况了,i 的值会影响到各个块里面的 i,等循环完后 i 等于10,所有块的i都变成了10了。这就是为什么第一段代码运行后会弹出数字10了,这并不是我们想要的。

就好比小明陆陆续续去了10个国家玩,每到一个国家都给自己弄了一个不同的身份,但是小明被告知以后只能用在第10个国家取得的那个身份,那么之前9个国家认识小明的朋友都会不认识他的,小明当场就懵逼了。

不足二

用var 声明变量的时候会出现“变量提升“的现象。

“ 变量提升“是什么鬼?新概念第一次听?前端君快来解释一下!

再看一段简短的代码:

var a = 1;
(function(){
   alert(a);
   var a = 2;
})();//结果:undefined

初学者可能认为:代码一开始已经定义了变量a,值为1,相当于全局变量,代码运行的时候会先弹出这个全局变量a的值:1;然后再重新给a赋值为2;可偏偏又事与愿违,心好累啊,它会告诉你结果是undefined; undefined就是未定义啊,为什么会是未定义呢?

原因就在于我们在代码块(函数内)里面还声明并定义了一个变量a,导致变量提升了,实际的代码执行顺序是这样的,仔细看完你就知道什么叫变量提升了。

var a = 1;
(function(){
   var a;
   alert(a);
   a = 2;
})();

对比一下两段简短的代码:var a = 2; 这句代码被拆分成两部分:声明var a ; 和 定义a = 2;而声明部分被提升(看到了吗?提升两个字出现了)到了代码块的前面,运行的时候自己挪到前面了,这就是“变量提升“,结果就是:先执行声明,接着就执行alert(a);变量a只是声明还没定义,就弹出了undefined了。

所以,归根结底就是“变量提升“在作怪。这就是var的又一大不足之处。那么,用let关键字在代码块就不会被提升了吗?是的,不提升了。

如果你用let这样重写刚刚那段代码的话:

var a = 1;
(function(){
   alert(a);
   let a = 2;
})();   // 结果:报错a未定义

用let关键字来定义a;这样a在代码块内就不会提升了。那为什么又报错了呢,因为用let声明的变量,在其块级作用域内是封闭的,是不会受到外面的全局变量a影响的,并且要先声明再使用,所以a的值即不是1(因为不受外面的影响),也不是undefined(因为先声明后使用),更不是2,未声明定义就使用,只有报错啦。

用let关键字也算是提醒我们,平时记得先声明定义再使用的好习惯。

光是var的不足就讲了这么长的篇幅,希望没把你们闷到,我尽量用一些生活的例子来打比方,如果你能能坚持看到这里很不错了,还有一点,再坚持一下。

这么说,let确实能弥补一些var的不足之处。那么使用let的时候还有什么要注意的吗?有的!

注意1:同一个块级作用域内,不允许重复声明同一个变量。

错误示范一:

{
  var a =1;
  let a =2;  //报错,因为a已经用var声明过
}

错误示范二:

{
  let a =1;
  let a= 2; //还是报错,a已经用let声明过。
}

注意2:函数内不能用let重新声明函数的参数

错误示范:

function say(word){
    let word = 'hello Jack';  //报错:用let重新声明word参数
   alert(word)
}
say('hello Lili');

say()函数内用let重新声明了word这个参数,会报错的,千万别这么干。

关于ES6新增的let关键字,前端君就讲述这么多,毕竟涉及到代码,需要集中精力来看,能坚持到看到这里同学,我要谢谢你们,说明这一节写得还算易懂!

本节总结

总结:用let声明变量只在块级作用域起作用,适合在for循环使用,也不会出现变量提升现象。同一个代码块内,不可重复声明的相同变量,不可重复声明函数内的参数。

本系列教程来自 web前端教程 微信公众号。

转载请注明:Rockyxia Web技术博客 » ES6第二节:ES6新增了let关键字,干嘛用的?
感谢阅读,如果您发现文章中有表述不准确,欢迎提出来,也欢迎交流相关问题,你可以去这里进行一对一问答交流。

(本篇完)