ES6学习笔记
1.
let声明的块级作用域 区别于 var(声明全局作用域)
不存在变量提升(TDZ)
不允许重复声明 (报错)
块级作用域: ES5中只有函数作用域和全局作用域。
块级作用域与函数声明:
ES5中,函数只能在顶层作用域和函数作用域之中声明。不准在块级作用域中声明。但是为了兼容,如果在块级作用域声明了则会提升到函数头部。
E56中,函数允许在块级作用域内声明, 行为类似VAR, 且声明会提升到当前块级作用域的顶部。
const 声明只读的常量。同let一样,只在声明的块级作用域内有效、不可重复声明。
const 对于基本类型数据(string, number, boolean) 保证值不变;对于复合类型数据(object, array) 保证变量指向的指针不变(属性可写,但重新赋值对象则报错)。
var、 function声明的全局变量仍是顶层对象的属性。
let、const、class声明的全局变量不属于顶层对象的属性。
2.
模式匹配 : 按照一定模式,从array、 object中提取值,并对变量进行赋值 就叫解构赋值。
默认值: 当解构模式有匹配值,且匹配值为UNDEFINED时(必须是===),则触发默认值作为返回结果。
若默认值为表达式,那么只有当用到的时候才会求值。 惰性求值
对象的解构赋值: 数组的元素是按次序排列的,变量的取值由位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
对象的解构赋值的实质: 先找到同名属性, 对属性的变量进行赋值。
函数参数的解构赋值:
A. function move({x = 0, y = 0} = {}) {}
B. function move({x, y} = { x: 0, y: 0 }) {} 是为函数move的参数指定默认值,而不是为变量x和y指定默认值
圆括号 :
不得使用在: 1.声明语句 2.函数参数 3.赋值语句的模式部分(类似Key)
可以使用在: 赋值语句的非模式部分(类似value)
3. 字符串的新增方法
一、String.fromCodePoint(0x20BB7) // “吉”
该方法定义在String对象上
二、codePointAt()方法是测试一个字符由两个字节还是由四个字节组成的最简单方法。
三、normalize()
四、以下皆是实例方法:
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
第二个参数表示开始搜索的位置。
除了 endsWitdh('hi', n) 表示针对前n个字符。
五、repeat(n) 返回一个新的字符串, 将原字符串重复n次
六、padStart()用于头部补全,padEnd()用于尾部补全。第一个参数表示补全的最大长度, 第二个参数表示用来补全的字符串。
eg: '12'.padStart(10, 'YYYY-MM-DD') // “YYYY-MM-12”
七、trimStart() 消除头部空格
trimEnd() 消除尾部空格
返回新字符串,不改变原字符串。
4. 正则的扩展
两种表达方式:
一、new RegExp('xyz','i'); 其中,第二个参数为正则表达式的flag(修饰符)
二、 new RegExp(/xyz/i);
5. 数值的扩展
二进制: 前缀加 0b(B)
八进制: 前缀加 0a(A)
6. 函数的扩展
- 函数参数的默认值: 为函数的参数设置默认值,即直接写在参数定义的后面。
通常, 带默认值的参数置于函数的尾部 - rest 参数(形式为…变量名),用于获取函数的多余参数,
rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。 - 箭头函数的三个特点:
不需要 function 关键字来创建函数
当且仅当只有一句表达式时,省略 return 关键字
继承当前上下文的 this 关键字。 即 this绑定箭头函数定义生效时所在的作用域,而不是指向运行时所在的作用域。
7. 数组的扩展
一、 扩展运算符:(spread)是三个点(...)。
它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。可以替代apply, 直接展开数组给函数传参
二、Array.from()用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象。
Array.from()还可以接受第二个参数,用来对每个元素进行处理,将处理后的值放入返回的数组。
三、数组实例的 find() 和 findIndex()find() 找出第一个符合条件的数组成员,并返回该成员。找不到则返回UndefinedfindIndex() 找出第一个符合条件的数组成员,并返回该成员的位置。找不到则返回 -1
四、可以用for…of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
8. 对象的扩展
- ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
- JavaScript 定义对象的属性,有两种方法:
obj.foo = true;// 直接用标识符作为属性名obj['a' + 'bc'] = 123;// 用表达式作为属性名
- super 关键字: this关键字总是指向函数所在的当前对象;super指向当前对象的原型对象。
- 对象的扩展运算符
对象的解构赋值用于从一个对象取值,相当于将目标对象自身的所有可遍历的、但未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面。
注意,解构赋值的拷贝是浅拷贝。
即如果一个键的值是复合类型的值(array、obejct、函数)、那么解构赋值拷贝的是这个值的引用,而不是这个值的副本。
9. 对象的新增方法
一、 Object.assign()方法用于对象的合并,是浅拷贝
二、 Object.keys、Object.values和Object.entries,作为遍历一个对象的手段,供for...of循环使用。Object.entries方法的一个用处是,将对象转为真正的Map结构:const obj = { foo: 'bar', baz: 42 };const map = new Map(Object.entries(obj));
map // Map { foo: “bar”, baz: 42 }
10. Symbol
Symbol 是一个原始类型的值,不是对象。它是一种类似于字符串的数据类型。表示独一无二的值.凡是属性名属于 Symbol 类型,可以保证不会与其他属性名产生冲突。
11. Set 和 Map 数据结构
一、 数据结构 Set 类似于数组,但是成员值唯一,不重复。另外,两个对象总是不相等的。
数组去重 [...new Set(array)]
字符串去重 [...new Set('ababbc')].join('')
二、Set实例的属性:size: 返回Set实例的成员总数。
三、Set实例的方法:
操作方法: 4个Set.prototype.add(value):添加某个值,返回 Set 结构本身。Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员。Set.prototype.clear():清除所有成员,没有返回值。Array.from方法可以将 Set 结构转为数组。
数组去重法二: Array.from(new Set(array));
遍历方法: 4个 (Set的遍历顺序就是插入顺序)Set.prototype.keys():返回键名的遍历器Set.prototype.values():返回键值的遍历器Set.prototype.entries():返回键值对的遍历器Set.prototype.forEach():使用回调函数遍历每个成员
Set 结构没有键名,只有键值(或者说键名和键值是同一个值) 可以省略values方法,直接用for…of循环遍历 Set。
eg. for (let x of set)
四、WeakSet
WeakSet 结构与 Set 类似,也是不重复的值的集合。
但是,它与 Set 有两个区别:
首先,WeakSet 的成员只能是对象,而不能是其他类型的值。
其次,WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用。
WeakSet 不能遍历,是因为成员都是弱引用,随时可能消失
五、Map
类似对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种 Hash 结构的实现。
任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构都可以当作Map构造函数的参数。
Map 的键实际上是跟内存地址绑定的。
属性:size属性返回 Map 结构的成员总数。
操作方法: Map.prototype.set(key, value) 返回整个 Map 结构。如果key已经有值,则键值会被更新,否则新生成该键。get(key) delete(key) has(key) clear()
遍历方法:Map.prototype.keys():返回键名的遍历器。Map.prototype.values():返回键值的遍历器。Map.prototype.entries():返回所有成员的遍历器。Map.prototype.forEach():遍历 Map 的所有成员。
Map 结构的默认遍历器接口就是entries方法for (let [key, value] of map)
七、 WeakMap 与Map结构类似,也是用于生成键值对的集合。
但是
1.只接受对象作为键名
2.且键名所指向的对象,不计入垃圾回收机制
12. Promise
Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。
resolve是将Promise的状态置为fullfiled,reject是将Promise的状态置为rejected。
只是new一个Promise对象,并没有调用它,但是传进去的函数就已经执行了Promise.resolve('foo')new Promise(resolve => resolve('foo'))
一、Promise.prototype.then()
then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。
二、Promise.reject()
reject的作用就是把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调。
三、Promise.prototype.catch()
用来指定reject的回调
四、Promise.all()
用Promise.all来执行,all接收一个数组参数,里面的值都是Promise实例。all()用来并行执行多个异步操作,并且在一个回调中处理所有的返回数据。
参数里的异步操作是并行执行的,等到它们都执行完后才会进到then里面。all会把所有异步操作的结果放进一个数组中传给then
五、Promise.race()
all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,race方法是: 谁跑的快,以谁为准执行回调。
13. for…of for…in iterator
for...of 用于遍历一个迭代器,如数组。for...in 用来遍历对象中的属性。
遍历器是一种接口,为各种不同的数据结构提供统一的访问机制。
任何数据结构只要部署 Iterator 接口,就可以完成遍历操作
tips
1.for...of循环调用遍历器接口,而数组的遍历器接口只返回具有数字索引的属性。
2.for...of 遍历Set结构时,返回的是一个值,而 遍历Map 结构时,返回的是一个数组,该数组的两个成员分别为当前Map成员的key和value。
3.对于普通的对象,for...in可以遍历键名,for...of会报错。
14. Generator
Generator 函数除了状态机,还是一个遍历器对象生成函数。
有两个特征:
- function关键字与函数名之间有一个星号。
- 函数体内部使用yield表达式,定义不同的内部状态。
调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。之后每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。
value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
yield表达式后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行,相当于“惰性求值”功能。
15. async
async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行时,遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到。
tips
1.await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try...catch代码块中。
2.多个await命令后面的异步操作,若不存在继发关系,最好让它们同时触发。通过Promise的all方法。
3.await命令只能用在async函数之中,用于普通函数会报错。
16. Module
模块功能主要由两个命令构成:export和import。
export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
export命令后面,使用大括号指定所要输出的一组变量。
import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块对外接口的名称相同。
import命令使用as关键字为输入的变量重命名。import命令输入的变量都是只读的。
export default命令,为模块指定默认输出。加载该模块时,import命令可以指定任意名字,这时import命令后面,不使用大括号。
17. Class
- constructor 方法
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。
一个类必须有constructor方法,如果没有显式定义,则会被默认添加空构造。
类必须使用new调用,否则会报错。 - 类的实例
实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)。
类的所有实例共享一个原型对象 - this 指向
类的方法内部如果含有this,它默认指向类的实例。
但若将方法提取出来单独使用,this会指向该方法运行时所在的环境(由于 class 内部是严格模式,所以 this 实际指向的是undefined),从而报错。
解决方法是使用箭头函数。
箭头函数内部的this总是指向定义时所在的对象,箭头函数位于构造函数内部,定义生效是在构造函数执行时。即运行环境,肯定是实例对象,所以this会总是指向实例对象。 - 静态方法
在一个方法前加上static关键字,表示该方法不会被实例继承,而是直接通过类来调用。
如果静态方法包含this关键字,这个this指的是类,而不是实例。
父类的静态方法,可以被子类继承,通过super调用。
18. Class的继承
Class 可以通过extends关键字实现继承父类的属性和方法。
子类必须在constructor方法中调用super方法,否则新建实例时会报错。
子类实例的构建,基于父类实例,只有super方法才能调用父类实例。
super虽然代表了父类的构造函数,但是返回的是子类的实例。
父类的静态方法,也会被子类继承。
在子类的静态方法中通过super调用父类的方法时,方法内部的this指向当前子类,而不是子类的实例。
- 本文作者:JSZ
- 本文链接:blog.vampuck.com/2020/12/09/es6_note/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!