前言
大家好,我是一只流浪的kk,当你看到这边博客的时候,说明你已经进入了ES6学习的领域了,从本篇博客开始,我将会将自己学习到ES6的相关知识进行整理,方便大家参考和学习,那么我将带你进入第一节的内容学习let和const命令,本篇博客从三个方面进行全方位解析。
let命令
首先我们需要学习的是let命令的使用,这个使用非常简单,它其实也是声明变量的一种方式,和var相比我把它的特点总结了如下四点,一起来看看吧!
(1):基本用法
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>let命令的基本用法</title> </head> <body> <script type="text/javascript"> let a=10; var b=20; console.log(a);//10 console.log(b);//20 </script> </body> </html>
我们看到我们现在是使用let关键字定义变量的,好处的话我们一步一步进行讲解
(2):不具备变量提升的能力
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>不具备变量提升的能力</title> </head> <body> <script type="text/javascript"> console.log(a);//报错 let a=10; console.log(b);//undefined var b=20; </script> </body> </html>
在这个案例中,我们看到使用let关键字定义的变量会报错,而使用var关键字定义的变量不会报错,这一进一步说明let关键字定义的变量不具备变量提升的能力,从而也时刻提醒我们养成良好的编程习惯,任何变量都应该遵循先定义后使用的原则。
(3):暂时性死区
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>let暂时性死区</title> </head> <body> <script type="text/javascript"> if(true){ tep='abc'; console.log(tep);//ReferenceErro let tep; console.log(tep);//undefined tep=123; console.log(tep);//123 } </script> </body> </html>
(4):不允许重复声明
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>不允许重复声明</title> </head> <body> <script type="text/javascript"> function bar(){ var a=10 let a=20; let b=10; let b=20; } bar();//报错 function foo(args){ { let args; } } foo();//不报错 </script> </body> </html>
块级作用域
在ES5中,我们只有函数级作用域和全局作用域,这对我们的开发带来很大的不方便,例如同事之间的开发,变量的定义可能会相同,这就有可能会造成代码发生错误,我先用一个例子来解释一下吧!
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>块级作用域</title> </head> <body> <script type="text/javascript"> let arr=[]; for(var i=0;i<10;i++){ arr[i]=function(){ console.log(i); } } arr[6](); </script> </body> </html>
在这里我们希望提到当前i,而最终结果是10,变量i
是var
命令声明的,在全局范围内都有效,所以全局只有一个变量i,每一次循环,变量i
的值都会发生改变,而循环内被赋给数组a
的函数内部的console.log(i)
,里面的i
指向的就是全局的i
。也就是说,所有数组a
的成员里面的i
,指向的都是同一个i
,导致运行时输出的是最后一轮的i
的值,也就是 10。那么如何解决呢?
我们再来看另一个示例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>块级作用域</title> <style type="text/css"> div { width: 100px; height: 100px; background: lightgreen; float: left; margin: 20px; font: 30px/100px "microsoft yahei"; text-align: center; } </style> </head> <body> <div>a</div> <div>b</div> <div>c</div> <div>d</div> <div>e</div> <div>f</div> <div>g</div> <div>h</div> <div>i</div> <div>j</div> <script type="text/javascript"> var divs=document.getElementsByTagName("div"); for (var i=0;i<divs.length;i++) { divs[i].onclick=function(){ alert(i); } } </script> </body> </html>
假定页面中有10个div,我们每点击一个div,我们想要弹出当前div的下标,但是都是弹出10,这就是和我们前面提到的情况一样,
解决方案一:使用闭包
在没有ES6之前,我们解决这类问题通常使用闭包,那么什么是闭包呢?以后的章节我会拿出来单独讲,这里讲一下浅显的字面意思:当一个内部函数被调用,就会形成闭包,闭包就是能够读取其他函数内部变量的
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>块级作用域</title> <style type="text/css"> div { width: 100px; height: 100px; background: lightgreen; float: left; margin: 20px; font: 30px/100px "microsoft yahei"; text-align: center; } </style> </head> <body> <div>a</div> <div>b</div> <div>c</div> <div>d</div> <div>e</div> <div>f</div> <div>g</div> <div>h</div> <div>i</div> <div>j</div> <script type="text/javascript"> var divs=document.getElementsByTagName("div"); for (var i=0;i<divs.length;i++) { divs[i].onclick=(function(n){ return function(){ alert(n); } })(i); } </script> </body> </html>
现在的话,我们每点击div一次都可以得到当前下标(索引)
解决方案二:使用块级作用域
使用块级作用可以快速解决这个问题
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>块级作用域</title> </head> <body> <script type="text/javascript"> let arr=[]; for(let i=0;i<10;i++){ arr[i]=function(){ console.log(i); } } arr[6](); </script> </body> </html>
在这里,let声明的变量仅在块级作用域内有效,变量i
是let
声明的,当前的i
只在本轮循环有效,所以每一次循环的i
其实都是一个新的变量,所以最后输出的是6
。你可能会问,如果每一轮循环的变量i
都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i
时,就在上一轮循环的基础上进行计算
const命令
(1):基本用法
const声明一个只读的常量,一旦声明,常量的值就不能改变,并且用const声明的常量必须全部大写,例如PI,MAX,MIN等等
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>const基本用法</title> </head> <body> <script type="text/javascript"> const PI=3.14; console.log(PI); PI=2 </script> </body> </html>
同样,使用const声明的变量不得改变值,所以说const一旦声明变量,就必须立刻初始化,不得留到以后赋值
(2):暂时性死区
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>const暂时性死区</title> </head> <body> <script type="text/javascript"> if(true){ const MIN=10 } console.log(MIN); if(true){ console.log(MAX); const MAX=10; } </script> </body> </html>
同样,使用const声明的变量也不具备变量提升的能力
(3):不允许重复声明
同样const命令也不允许重复声明,我们来看下面的例子
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>const不可重复声明变量</title> </head> <body> <script type="text/javascript"> var message='hello world'; let age=18; const message='你好';//报错 const age=20;//报错 </script> </body> </html>
在这里我们用const重复声明变量,控制台输出Uncaught SyntaxError: Identifier 'message' has already been declared,所以const也不允许重复声明变量
ES6声明变量的六种方法
在ES5中我们只有var,function两种声明变量的方法,但是在ES6中新增了let,const,import,class等四种声明变量的方法,所以现在我们一共有六种声明变量的方法,在之后的博客中我们回对import,class进行讲解。
总结
本篇博客我们一共学习了三个知识点,let命令,块级作用域,const命令,以及总结了let命令和const命令的相似之处,这只是简单的ES6入门,下一篇博客是讲解变量的解构赋值。