ES6笔记之let声明和const

博主为何要在繁忙的业务中抽时间写这些最基本的笔记,就是想不断积累本身小的细节,让本身的开发更有效率,不能知其然不知因此然。javascript

博主在实际开发中使用了react全家桶(框架)+typescript(预编译JS)+ES6(JS语法)+webpack(打包工具)+styledcomponent(css),并使用node模拟后台数据。css

由于本身不想成为写业务 的机器, 而是致力成为 技术 人员。html

ES6分类博文笔记摘自 http://es6.ruanyifeng.com/#docs/let  java

博主在这里只写最核心和本身所须要的。node

let 命令react

let命令 用来声明变量 ,与var的区别就是let所声明 的变量 做用域只在let 命令所在的代码块{}有效,且须要先声明后使用,若是直接使用会报错webpack

a[i]()//这里i从0到9都会打印10var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); };
 a[i]();//这里依次打印0到9 }

变量ivar声明的,在全局范围内都有效,因此全局只有一个变量i。每一次循环,变量i的值都会发生改变,es6

而循环内被赋给数组afunction在运行时,会经过闭包读到这同一个变量i,(其实我这里也不是特别理解,得从新补习一下闭包)致使最后输出的是最后一轮的i的值,也就是10。web

  var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6

变量ilet声明的,当前的i只在本轮循环有效,因此每一次循环的i其实都是一个新的变量,因此最后输出的是6。你可能会问,若是每一轮循环的变量i都是从新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是由于 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。 typescript

另外一个var和let的区别

var命令会发生”变量提高“现象,即变量能够在声明以前使用,值为undefined。这种现象多多少少是有些奇怪的,按照通常的逻辑,变量应该在声明语句以后才可使用。

为了纠正这种现象,let命令改变了语法行为,它所声明的变量必定要在声明后使用,不然报错。(webstorm会自动检测,而不是在编译后检测报错,推荐使用)

// var 的状况 console.log(foo); // 输出undefined var foo = 2;  // let 的状况 console.log(bar); // 报错ReferenceError let bar = 2;

上面代码中,变量foovar命令声明,会发生变量提高,即脚本开始运行时,变量foo已经存在了,可是没有值,因此会输出undefined。变量barlet命令声明,不会发生变量提高。这表示在声明它以前,变量bar是不存在的,这时若是用到它,就会抛出一个错误。

暂时性死区

这里原博主说了不少,可是简而言之就是若是在一个代码块中在let申明一个变量前使用了当前申请的变量,及时该变量已在外部声明,即会抛出错误。

那有人会问了,既然抛出错误让代码不能执行,我平时用js都不会有这样的问题,那我用let的意义在哪里呢?

为了让你们养成良好的编程习惯,变量必定要在声明以后使用,不然就报错。

// 不报错 var x = x;  // 报错 let x = x; // ReferenceError: x is not defined

上面代码报错,也是由于暂时性死区。使用let声明变量时,只要变量在尚未声明完成前使用,就会报错。上面这行就属于这个状况,在变量x的声明语句尚未执行完成前,就去取x的值,致使报错”x 未定义“。

ES6 规定暂时性死区和letconst语句不出现变量提高,主要是为了减小运行时错误,防止在变量声明前就使用这个变量,从而致使意料以外的行为。这样的错误在 ES5 是很常见的,如今有了这种规定,避免此类错误就很容易了。

不容许重复声明

let不容许在相同做用域内,重复声明同一个变量

块级做用域

ES5 只有全局做用域和函数做用域,没有块级做用域,这带来不少不合理的场景。

第一种场景,内层变量可能会覆盖外层变量。

var tmp = new Date(); function f() { console.log(tmp);//因为下面变量提高,即会输出undefined if (false) { var tmp = 'hello world';//没有块级做用域的限制,这里声明的tmp在ES5中会提高至函数做用域。虽然不会执行里面的赋值,可是会变量提高 } } f(); // undefined

第二种场景,用来计数的循环变量泄露为全局变量。

var s = 'hello'; for (var i = 0; i < s.length; i++) { console.log(s[i]); } console.log(i); // 5

上面代码中,变量i只用来控制循环,可是循环结束后,它并无消失,泄露成了全局变量。

 

ES6 的块级做用域

let实际上为 JavaScript 新增了块级做用域。

ES6 容许块级做用域的任意嵌套。

块级做用域与函数声明(不理解也不要紧,本篇主要讲解let)

if (true) { function f() {} }  // 状况二 try { function f() {} } catch(e) {  // ... }

上面两种函数声明,根据 ES5 的规定都是非法的。

可是,浏览器没有遵照这个规定,为了兼容之前的旧代码,仍是支持在块级做用域之中声明函数,所以上面两种状况实际都能运行,不会报错。

ES6 引入了块级做用域,明确容许在块级做用域之中声明函数。ES6 规定,块级做用域之中,函数声明语句的行为相似于let,在块级做用域以外不可引用。

function f() { console.log('I am outside!'); } (function () { if (false) {  // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }());

上面代码在 ES5 中运行,会获得“I am inside!”,由于在if内声明的函数f会被提高到函数头部,实际运行的代码以下。

// ES5 环境 function f() { console.log('I am outside!'); } (function () { function f() { console.log('I am inside!'); } if (false) { } f(); }());

而在ES6中,因为f()未声明,因此会报错

原来,若是改变了块级做用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻所以产生的不兼容问题,ES6在附录B里面规定,浏览器的实现能够不遵照上面的规定,有本身的行为方式

  • 容许在块级做用域内声明函数。
  • 函数声明相似于var,即会提高到全局做用域或函数做用域的头部。
  • 同时,函数声明还会提高到所在的块级做用域的头部

注意,上面三条规则只对 ES6 的浏览器实现有效,其余环境的实现不用遵照,仍是将块级做用域的函数声明看成let处理。

const 

const也能够用来申明变量 可是声明的是常量。一旦声明,常量的值就不能改变。

当咱们尝试去改变用const声明的常量时,浏览器就会报错。const有一个很好的应用场景,就是当咱们引用第三方库的时声明的变量,用const来声明能够避免将来不当心重命名而致使出现bug:

相关文章
相关标签/搜索