es6重点笔记:let,const
一,let
先看代码:
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i)
};
}
a[6](); // 10
我先花点时间来拆分一下这个for循环,我就写第一个循环过程,后面依次类推:
{
var i = 0;
if (i<10) {
a[i] = function(){
console.log(i)
}
};
i++;
}
// 第一个循环
{
i = 1;
...;
i++;
}
// 第二个循环
。。。
每一次for循环都是一个代码块,上面用大括号区分开来,es5没有块级作用域的概念,所以等同于没有大括号,i就是全局作用域下的变量,if句里面的代码块是子作用域,因此能访问到它的父作用域,就是for循环的设置循环条件的部分,所以i的值是同一个,就是全局环境下的i,因此for循环执行完成后,i就是10,你不管怎么访问,i都是10;
上面的代码要想实现我们预期的效果很简单,把var换成let就可以了,里面的原理是:由于es6有了块级作用域的概念,let声明的i只对它本轮(也就是大括号里的)循环有效,也就是说每一次循环都相当于重新声明了i,所以每次循环(代码块内)都互不干涉,因此能够依次输出不同的i,但是问题来了:如果不是同一个i,为什么i还会叠加呢?每次循环的时候它是访问不到上一轮的i的,因为是不同的块级作用域啊(不同的大括号里)。重点来了:因为JavaScript引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
这才是考察的重点!
暂时性死区:在let命令声明变量之前,该变量都是不可用的。
typeof一定百分之百安全吗?es5是这样,es6不是了,因为存在暂时性死区。
关于暂时性死区有一个很有趣的例子,挺绕的:
var x = 1;
fucntion f(y=x){};
f();
// 不报错 var x = 1;
function f(x=x){};
f();
// 报错,注意这里的错误不是x已经被定义了,而是x未定义
为什么第一个不报错,第二个报错呢?x不应该是取的外面全局下的值吗?
其实第二个里面隐藏了一个暂时性死区:
函数声明时,参数部分实际上就是一个块级作用域,y=x,实际上等同于let y = x,x在块级作用域里找不到定义,所以到外部全局下去找,找到了,所以不报错,x=x,实际上等同于let x = x,但此时x不会去块级作用域外面找,为什么,因为块级作用域内部有定义let x,所以它没有找到对应的值,因此报错not defined。
块级作用域:
首先,有哪些作用域:全局作用域,块级作用域,还有函数作用域(这个最容易忘,面试的坑)
为什么要块级作用域:1,内层变量可能会覆盖外层变量;2,用来计数的循环变量泄露为全局变量,造成内存泄漏,污染环境。(面试的坑)
es5规定,函数只能在顶层作用域和函数作用域中声明,不能在块级作用域中声明。就比如在if句中声明一个function函数,这就会报错,但在es6中不会。
function f(){ console.log(1); }
(function (){
if (false) {
function f(){ console.log(2); }
}
f();
}());
上面的代码,如果在es5中运行,if条件中的function会直接跑到if外面去,然后执行,最后输出2。但如果在es6中,允许在块级作用域中声明函数,所以函数不会跑到if条件句外面,那么f()应该调用的是外面的函数声明,理论上应该会输出1,但实际上会报错,为什么?有人解释说也是因为块级作用域里不能声明函数,那把f()放在if语句中并不会报错,说明是可以在块级作用域中声明的。
重点来了:es6的浏览器有自己的行为方式:
1,允许在块级作用域内声明函数;
2,函数声明类似于var,会提升到全局作用域下或函数作用域的头部;
3,函数声明会提升到所在的块级作用域的头部;
有了上面三条,刚刚的代码就等同于下面:
function a(){ console.log(1); }
(function (){
var f = undefined;
if (false) {
function a(){ console.log(2); }
}
f();
}());
所以f还没有定义是一个function,因此不能执行。
二,const
const大部分的注意点都和let差不多。但是要注意下面的
es6重点笔记:let,const的更多相关文章
- es6重点笔记:Symbol,Set,Map,Proxy,Reflect
一,Symbol 原始数据类型,不是对象,它是JavaScript第七种数据类型,表示独一无二的值.Symbol是通过Symbol函数生成的: let s = Symbol(); typeof s / ...
- es6重点笔记:数值,函数和数组
本篇全是重点,捡常用的怼,数值的扩展比较少,所以和函数放一起: 一,数值 1,Number.EPSILON:用来检测浮点数的计算,如果误差小于这个,就无误 2,Math.trunc():取整,去除小数 ...
- ES6重点--笔记(转)
最常用的ES6特性 let, const, class, extends, super, arrow functions, template string, destructuring, defaul ...
- es6重点笔记:对象
1,Object.is():比较两个值是否严格相等,es5的'===',不能判断+0和-0,还有NaN,但是es6的Object.is()可以区分 Object.is(+0, -0); // fals ...
- ES6学习笔记<一> let const class extends super
学习参考地址1 学习参考地址2 ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015:也 ...
- ES6入门笔记
ES6入门笔记 02 Let&Const.md 增加了块级作用域. 常量 避免了变量提升 03 变量的解构赋值.md var [a, b, c] = [1, 2, 3]; var [[a,d] ...
- C++编程思想重点笔记(下)
上篇请看:C++编程思想重点笔记(上) 宏的好处与坏处 宏的好处:#与##的使用 三个有用的特征:字符串定义.字符串串联和标志粘贴. 字符串定义的完成是用#指示,它容许设一个标识符并把它转化为字符串, ...
- es6学习笔记-class之一概念
前段时间复习了面向对象这一部分,其中提到在es6之前,Javasript是没有类的概念的,只从es6之后出现了类的概念和继承.于是乎,花时间学习一下class. 简介 JavaScript 语言中,生 ...
- ES6学习笔记<五> Module的操作——import、export、as
import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...
随机推荐
- python的range()函数
range函数的三种用法:>>> range(1,5) # 代表从1到5(不包含5) [1, 2, 3, 4] >>> range(1,5,2) # 代表从1到5, ...
- python 模块:csv
转自:http://www.cnblogs.com/sislcb/archive/2008/12/15/1355481.html (感谢整理) 举几个例子来介绍一下,Python 的 CSV模块的使用 ...
- Redis锁构造
单线程与隔离性 Redis是使用单线程的方式来执行事务的,事务以串行的方式运行,也就是说Redis中单个命令的执行和事务的执行都是线程安全的,不会相互影响,具有隔离性. 在多线程编程中,对于共享资源的 ...
- Django入门实战【3步曲】
环境准备 junhongdeMacBook-Air:site-packages junhongchen$ python -V Python 2.7.10 junhongdeMacBook-Air: ...
- Windows下搭建Redis服务器
Redis服务器是当下比较流行的缓存服务器,Redis通常被人拿来和Memcached进行对比.在我看来,应当是各具优势吧,虽然应用场景基本类似,但总会根据项目的不同来进行不通的选用. 我们今天主要讲 ...
- Java学习笔记6---字符串比较方法compareTo(String str)
方法原型为int compareTo(String str),返回值为int型,参数为字符串类型. 下面是简单示例: /* * compareTo()返回参与比较的两个字符串的ascii码差值 * O ...
- Jerry的CDS view自学系列
My CDS view self study tutorial - part 1 how to test odata service generated by CDS view https://blo ...
- CSS选择器:伪类(图文详解)
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 伪类(伪类选择器) 伪类:同一个标签,根据其不同的种状态,有不同的样式. ...
- [转载]mysql创建临时表,将查询结果插入已有表中
今天遇到一个很棘手的问题,想临时存起来一部分数据,然后再读取.我记得学数据库理论课老师说可以创建临时表,不知道mysql有没有这样的功能呢?临时表在内存之中,读取速度应该比视图快一些.然后还需要将查询 ...
- .net 平台下, Socket通讯协议中间件设计思路(附源码)
.net 平台下,实现通讯处理有很多方法(见下表),各有利弊: 序号 实现方式 特点 1 WCF 优点:封装好,方便.缺点:难学,不跨平台 2 RocketMQ,SuperSocket等中间件 优点: ...