- 第一节:什么是 ES6?新手该如何理解
- 第二节:ES6 新增了 let 关键字,干嘛用的?
- 第三节:ES6 中另一个不得不说的关键字 const
- 第四节:教你如何快速让浏览器兼容 ES6 特性
- 第五节:一个令人兴奋的 ES6 新特性:解构赋值
- 第六节:ES6 为字符串 String 带来哪些好玩的特性?
- 第七节:ES6 为数值做了哪些扩展?
- 第八节:ES6 为数组做了哪些扩展?
- 第九节:ES6 为对象做了哪些扩展?
- 第十节:ES6 为函数做了哪些扩展?
- 第十节:函数的扩展 — 箭头函数的 this 使用(补课)
- 第十一节:JavaScript 有了一种全新的数据类型:Symbol
- 第十二节:ES6 Proxy 代理 和 去银行存款有什么关系?
- 第十三节:易学又实用的新特性:for...of
- 第十四节:ES6 的 Iterator 遍历器到底是什么?
- 第十五节:有一种特殊的函数叫:Generator 函数
- 第十六节:ES6 新增的 Set 和 WeakSet 是什么东西?
- 第十七节:ES6 新增的 Map 和 WeakMap 又是什么东西?
- 第十八节:教你如何使用 ES6 的 Promise 对象
- 第十九节:终于 JavaScript 也有了类(Class)的概念
- 第二十节:一个缺失已久的特性 module 模块
第二节:ES6 新增了 let 关键字,干嘛用的?
大白话,讲编程,连载的第一节,得到大家的认可和赞赏,谢谢支持。文章还出现了几个错别字,惭愧!此外,连载的频率初定为每周2节,时间大约在早上10:00;大家对此有何建议都可以留言,前端君都会回复。
来吧,开始本节的学习!
ES6 给开发者带来很多令人激动的特性,其中let关键字就是其中之一。
那么,let关键字是什么东西?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论