前言:最近开始阅读阮一峰老师的《ECMAScript 6 入门》(以下简称原文)学习ECMAScript6(以下简称ES6)的知识,整理出一些知识点,加上自己的理解来做文章笔记。以章为单位,一章一注。文章代码与目录结构和原文不同。本章原文链接let和const命令。letlet用于声明一个变量。与var不同的是,会有变量提升(下面介绍),let声明的变量值只在let命令所在的代码块中有效。同一个作用域(后述)不能使用let重复声明同一个变量。注意:声明一个变量没有变量提升,不能重复。该声明仅在let命令所在的代码块中有效。让样本=1;样本=2;让样本=2;//会报错{letsample=1;控制台日志(示例);//正常输出1}console.log(sample);//会报错,因为它只在let命令所在的代码块中有效。constconst用于声明一个只读常量。一旦声明,常量的值就不能改变。如果您尝试更改常量的值,将会报告错误。而且const声明的时候必须要赋值,只声明不赋值会报错。同一个作用域不能用const重复声明同一个常量。const和let一样,因为作用域的原因,只能在它所在的代码块内有效。const实际上保证的不是变量的值不能改变,而是变量指向的内存地址中存储的数据不能改变。注意:声明常量不可更改后,必须对其赋值,不能重复。该语句在const命令所在的代码块中有效。常量样本=1;样本=2;//会报错,const声明的变量不能重新赋值constsample;//直接报错。声明const时,必须为其分配一个值。引入let和const之后,let已经可以代替var了。如果可以在let和const之间使用const,就尽量使用const。let和const的区别let和const的区别是一个声明变量,一个声明常量。变量可以重新赋值,但常量不能重新赋值。让sampleLet=2;constsampleConst=1;sampleLet=3;//正常sampleConst=3;//报错let和const只能先声明后使用,不能提升变量。两者都不能在同一范围内重复声明。它们只在命令所在的代码块中有效{sampleLet;//错误sampleConst;//错误letsampleLet=2;constsampleConst=1;让sampleLet=3;//错误常量sampleConst=3;//报错}sampleLet;//报错sampleConst;//报错变量提升(Hoisting)在ES6之前,使用var声明变量时,会出现一种叫做变量提升的特性。无论在代码的什么地方声明,它都会被提升到当前作用域的顶部。这种行为称为变量提升。为了纠正这种现象,let命令改变了语法行为。它声明的变量必须在声明之后使用,否则上面会报错。let和const表示变量不能被提升。这是真的?事实上,在JavaScript中,所有代表var、let、const、function、function*、class的声明都会被提升。let和const声明的变量会在环境实例化时创建,但是在变量的词法绑定之前不允许以任何方式访问它们,也就是说,当你在声明之前调用变量时会报错但是错误消息不是未定义的,在初始化之前无法访问。这也引出了下一个概念,称为临时死区。//var声明会增加变量,不会报错,但是值为undefinedconsole.log(sampleVar);//undefinedvarsampleVar=1;//let语句不会增加变量,但是报错不是未定义console.log(sampleLet);//Cannotaccess'sampleLetbeforeinitializationletsampleLet=1;//const声明不会提升变量,但错误未定义console.log(sampleConst);//不能在初始化前访问'sampleConst'constsampleConst=1;//直接使用没有声明的变量报“未定义”console.log(sample);//sampleisnotdefinedTemporarydeadzoneES6规定如果代码块中有let和const命令声明的变量,这个块会把这些变量从一开始就形成一个封闭的作用域,之前对这些变量的任何使用声明将导致错误。这些变量只有在声明语句完成后才能被访问(get或set),这在句法上称为“时间死区”(英文temporaldeadzone,简称TDZ),即代码块开始到结束之间的时间段完成变量声明语句。区域。varsample=1;if(true){样本='1';//报错letsample;}简单的说就是let和const命令声明的变量,在进入声明代码所在作用域时已经存在,但不能获取或使用,直到声明声明完成。块级作用域Scope(作用域,或译为有效作用域)是变量和函数的可访问作用域,即作用域控制着变量和函数的可见性和生命周期。let和const块级作用域作用域对于ES6来说并不陌生,但在ES5中只有全局作用域和函数作用域。为了解决块级作用域,ES6可以使用**let**和**const**声明块级作用域的变量。var声明的变量具有变量提升的特性,因此没有块的概念,可以跨块访问,但不能跨函数访问。外部作用域无法读取内部作用域中的变量。{//块作用域varsampleVar=1;让sampleLet=2;constsampleConst=3;控制台日志(示例变量);//成功输出1console.log(sampleLet);//成功输出2console.log(sampleConst);//成功输出3}console.log(sampleVar);//成功输出1console.log(sampleLet);//错误未定义console.log(sampleConst);//ErrornotdefinedES6允许块级作用域任意嵌套。同一个作用域不能使用let或const声明同一个变量,内层作用域可以定义一个与外层作用域同名的变量。{{{让样本='你好世界';//外部范围{letsample='sample';}//没有错误{console.log(sample);}//正常输出'HelloWorld'}}}块级作用域和函数声明ES5规定函数只能在顶层作用域和函数作用域中声明,不能在块级作用域中声明。ES6规定在块级作用域内,函数声明语句的行为类似于**let**,不能在块级作用域外引用。/*ES5,这两种情况都是非法的,因为两个函数声明都是在块范围内声明的。但是,为了与旧代码兼容,浏览器仍然支持在块级范围内声明函数。所以不会报错*/if(true){functionsampleFn(){}}try{functionsampleFn(){}}catch(e){//...}/*ES6,函数声明的行为语句类似于let,不在块级范围外引用*/if(true){sampleFn();//正常输出,函数声明语句的行为类似于letfunctionsampleFn(){console.log('HelloWorld');}}//但实际上在块级作用域外也可以引用函数,只是取值为undefinedif(false){functionsampleFn(){console.log('HelloWorld');}}console.log(sampleFn);//正常输出undefinedsampleFn();//错误报告为sampleFdddnisnotdefined为什么可以在块级范围之外引用函数?如果改变声明在块级范围内的函数的处理规则,显然会对旧代码产生很大的影响。为了缓解由此产生的不兼容问题,ES6在附录B中规定浏览器实现可以不遵循上述规定(指函数声明语句的行为),而有自己的行为。允许在块级范围内声明函数。函数声明类似于**var**,即被提升到全局作用域或函数作用域的头部。同时,函数声明也会被提升到它所在的块级作用域的头部。请注意,以上三个规则仅对ES6浏览器实现有效。其他环境下的实现无需遵守,块级函数声明仍按let处理。我们应该避免在块范围内声明函数。如果需要,也应该写成函数表达式,而不是函数声明语句。//函数声明语句,不要在块作用域中使用,因为会有变量提升{functionsampleFn(){console.log("HelloWorld");}}//函数表达式,在块作用域中,函数不会有变量提升{constsampleFn=function(){console.log("HelloWorld");}}顶级对象顶级对象是指浏览器环境中的窗口对象。在ES5中,顶级对象的属性等同于全局变量。为了改变这一点,ES6一方面规定,为了保持兼容性,var命令和function命令声明的全局变量仍然是顶级对象的属性;另一方面,规定了let命令、const命令、class命令声明的全局变量、Properties不属于顶级对象。/*在ES5中,顶层对象的属性赋值和全局变量的赋值是一回事。*/window.sample=1;console.log(window.sample);//正常输出1sample=2;console.log(window.sample);//正常输出2/*ES6,letcommand,constcommand,类命令声明的全局变量不是顶层对象的属性.*/varsampleVar=1;console.log(window.sampleVar)//正常输出1letsampleLet=1;console.log(window.sampleLet)//正常输出undefinedletsampleConst=1;console.log(window.sampleConst)//正常输出undefinedwindow提供了全局环境(即全局作用域),所有代码都在这个环境中运行。函数中的this,如果函数不是作为对象方法运行,而只是作为函数运行,this会指向顶层对象。但是,在严格模式下,此时这将返回undefined。不管是严格模式还是普通模式,newFunction('returnthis')()都会返回全局对象。函数sampleFn(){console.log(this);}sampleFn();//正常输出全局对象windowfunctionsampleFn1(){"usestrict";console.log(this)}sampleFn1();//通常输出undefined//启用严格模式"usestrict";constsample=newFunction('returnthis')();console.log(sample);//正常输出全局对象窗口
