ES6 学习笔记
一、let和const
1. let,const不存在变量提升,只在声明所在的块级作用域中有效。
![](https://img.haomeiwen.com/i5637778/7b0163d97de195a2.png)
2. Es5只有全局作用域和函数作用域,Es6添加了块级作用域。
3. 考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
4. 对于复合类型的变量,变量指向数据所在的地址,不保证该地址的数据不变,所以在将对象声明为常量时必须特别小心。
![](https://img.haomeiwen.com/i5637778/6f9fa721076c105f.png)
5.let, const, class定义的全局变量与顶层对象脱钩
二、变量的解析赋值
1. 对象的解析赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。如:
![](https://img.haomeiwen.com/i5637778/db0d638588dcff1d.png)
2. 解析也可用于嵌套结构的对象,如
![](https://img.haomeiwen.com/i5637778/4c6df0480e129667.png)
3. 对象的解析赋值,可以很方便的将现有对象的方法,赋值到某个变量,如
![](https://img.haomeiwen.com/i5637778/bcdcc42b9f0c634d.png)
4. 圆括号问题,解析赋值解析圆括号时很麻烦,只要由可能,就不要在模式中放置圆括号。另外:
* 变量声明语句中,不能带有圆括号
* 函数参数中,模式不能带有圆括号
* 赋值语句中,不能将整个模式,或嵌套模式中的一层,放在圆括号中
三、字符串的扩展
1. JS内部,字符以UTF-16的格式存储,每个字符固定为2个字节。对于那些需要4个字节存储的字符(Unicode码大于0xFFFF的字符),JS会认为它们是两个字符。
2. Es6提供的codePointAt方法,直接使用时参数也不能正确识别,如下面的字符串中,a的位置应该是1,但必须传入2才能取到字符,解决的办法是使用for...of循环,它能正确识别32位的UTF-16字符。
![](https://img.haomeiwen.com/i5637778/839f7903fec3deb6.png)
3. Es6中提供了另外操作32位的UTF-16的函数:String.fromCodePoint(), at(), includes(), startsWith(), endsWith()如
![](https://img.haomeiwen.com/i5637778/68d55639fd3e4f40.png)
4.模板字符串
![](https://img.haomeiwen.com/i5637778/cced73b8a31d94f7.png)
四、数值
1. 二进制和八进制的表示法分别使用前缀0b/0B和0o/0O。
2. 新的函数Number.isFinite(), Number.isNaN(), Number.parstInt(), Number.parseFloat(), Number.isInteger(),
![](https://img.haomeiwen.com/i5637778/863dddee04ba5d89.png)
在JS内部,整数和浮点数是同样的存储方法,所以3和3.0被视为同一个值。
3. 安全整数检测Number.isSafeInteger(), Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER。
![](https://img.haomeiwen.com/i5637778/0cc8e7cc0091ead4.png)
在使用Number.isSafeInteger()时,不能只验证运算结果,而要同时验证参与运算的每个值。
4. ES6在Math对象上新增了17个与数学相关的方法。
五、数组
1. Array.from()用于将类似数组的对象(含有length属性)和可遍历的对象(包括ES6新增的数据结构Set和Map)转换为数组
![](https://img.haomeiwen.com/i5637778/06a25a26e2eb9451.png)
2. Array.of()用来将一组值转换为数组,主要目的是弥补Array()和new Array()由于参数的不同导致的行为的差异,如
![](https://img.haomeiwen.com/i5637778/1ffaaad4d9e11a06.png)
3. 数组实例的copyWithin(),在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员)。
![](https://img.haomeiwen.com/i5637778/749fa06843855a5d.png)
4. 数组实例的find()和findIndex()函数
![](https://img.haomeiwen.com/i5637778/0fc4c24d93ac8f5f.png)
5. 数组实例的includes()函数
![](https://img.haomeiwen.com/i5637778/8a9f0c041b29ccfe.png)
同Set结构的has()方法一样,数组的includes()函数是用来查找值的;而Map结构的has()方法是用来查找键名的。
6.由于空位的处理规则非常不统一,所以要避免出现空位的情况。
六、函数
1. 函数默认值
![](https://img.haomeiwen.com/i5637778/36da721f6fa9a192.png)
2. 函数的length属性,表示该函数预期传入的参数个数。如果参数有默认值,则length不包含这个参数。同理,rest参数也不会计入length属性
3. 如果将参数默认值设为undefined,表明这个参数是可以省略的。
functionfoo(bar = undefined){......}
4. rest参数,形式为“...变量名“,用于获取函数的多余参数,这样就不需要使用arguments对象了。
![](https://img.haomeiwen.com/i5637778/3459f7ec43acd63f.png)
5. 扩展运算符“...” ,它的作用是将一个数组转为用逗号分隔的参数序列。
![](https://img.haomeiwen.com/i5637778/1f013e7a3a1c75a7.png)
扩展运算符内部调用的是数据结构的Iterator借口,因此只要具有Iterator接口的对象,都可以使用扩展运算符,比如Map结构。
![](https://img.haomeiwen.com/i5637778/53ef2f1572afd774.png)
6. 箭头函数
![](https://img.haomeiwen.com/i5637778/d0c3ff0b3252effe.png)
如果没有参数,或多个参数,就使用一个圆括号代表参数部分
![](https://img.haomeiwen.com/i5637778/fec17fe042603306.png)
感觉添加一个小括号比较好,这样可以统一起来
7.箭头函数中的this,指向固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。
![](https://img.haomeiwen.com/i5637778/0106b37a1acfad3b.png)
上面的代码中,只有一个this,就是函数foo的this,所以t1,t2,t3输出同样的结果,因为内部所以的箭头函数都没有自己的this,他们的this实际都是最外层foo函数的this。
长期以来,Js的this对象一直都是一个令人头疼的问题,在对象方法中使用this,必须非常小心,箭头函数“绑定”this,很大程度上解决了这个困扰。
7.尾调用优化和尾递归
七、对象,允许使用变量和函数,作为对象的属性和方法
1.简洁表示法
![](https://img.haomeiwen.com/i5637778/b3f598645fd46419.png)
2.判断两个值是否相等使用Object.is()
3.Object.assign()方法用于对象的合并,将源对象source的所有可枚举属性,复制到目标对象target。
![](https://img.haomeiwen.com/i5637778/f412ec859d97b837.png)
如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性
Object.assign方法是浅拷贝,如果源对象某个属性的值是对象,则目标对象拷贝得到的是这个对象的引用。
Object.assign()的用途
为对象添加属性
为对象添加方法
克隆对象
合并多个对象
为属性指定默认值
4.遍历对象 Object.keys, Object.values, Object.entries
5.扩展运算符
![](https://img.haomeiwen.com/i5637778/27f3843169df86b4.png)
八、Set和Map
1. Set类似于数组,但它的成员值都是唯一的。
* keys():返回键名的遍历器* values():返回键值的遍历器* entries():返回键值对的遍历器* forEach():使用回调函数遍历每个成员> 扩展运算符...内部使用for...of循环,所以也可以用于Set结构
九、一些不常用的功能
1. SIMD(Single Instruction/Multiple Data),即单指令,多数据
它是JS操作CPU对应指令的接口,可以使用一个指令,完成多个数据的运算,所以被广泛用于3D图形运算、物理模拟等运算量超大的项目之中。
SIMD是数据并行处理(parallelism)的一种手段,可以加速一些运算密集型操作的速度。
十、编程风格
1. let和const
let取代var
所有的函数都应该设置为常量
长远来看,JS可能会有多线程的实现,let表示的变量,这时let表示的变量,只应出现在单线程运行的代码中,不能是多线程共享的,这样有利于保证线程安全。
2. 字符串
静态字符串一律使用单引号或反引号,不使用双引号
动态字符串使用反引号
3.解构赋值
使用数组成员对变量赋值时,优先使用解构赋值
函数的参数如果是对象的成员,优先使用解构赋值
![](https://img.haomeiwen.com/i5637778/0f1471b01bb5246c.png)
如果函数返回多个值,优先使用对象的解构赋值,而不是数组的解构赋值
![](https://img.haomeiwen.com/i5637778/71119275d8b3beb3.png)
4. 对象
单行定义的对象,最后一个成员不以逗号结尾。多行定义的对象,最后一个成员以逗号结尾
对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性不可避免,要使用Object.assign方法
如果对象的属性名是动态的,可以在创造对象的时候,使用属性表达式定义。
![](https://img.haomeiwen.com/i5637778/658fdc2bc12c6743.png)
5.数组
使用扩展运算符(...)拷贝数组
使用Array.from方法,将类似数组的对象转为数组
6.函数
立即执行函数可以写成箭头函数的形式
![](https://img.haomeiwen.com/i5637778/ce79184b7f25aceb.png)
简单的、单行的、不会复用的函数,建议采用箭头函数。如果函数体较为复杂,行数较多,还是应该采用传统的函数写法
7. Map和Object
只有模拟现实世界的实体对象时,才使用Object。如果只是需要key : value的数据结构,使用Map结构。因为Map有内建的遍历机制
8. 使用ESLint