ES6 是 2015 版本的 JavaScript 标准,我们平时在项目中也经常用到 ES6 的新特性。
我打算重新学习一下 ES,主要的资料包括阮一峰的《ES6 标准入门》第三版和《深入理解ES6》。然后本篇文章是做的笔记。
let 和 const
let
let 是块级作用域,特别合适 for 循环,因为每次都会重新声明一新的变量。
let 没有变量提升,未声明直接使用会报错报错ReferenceError,而 var 有变量提升,会返回一个 undefined。
在 let 变量声明之前,都是暂时性死区,都会报错。
let 不允许重复声明。
在 ES6中,没有大括号不产生块级作用域。
const
const 声明一个只读的常量,一旦声明,声明的同时要立即复制,不然会报错。其它的的特性,比如重复声明,暂时性死区跟 let 一样。
const 声明的变量不可变是指,声明变量的内存地址不可变,但是数据结构是可变的。比如声明一个对象或者数组,可以不断往数组里面添加新的值。
最佳实践: 默认使用 const ,除非知道后面变量修改,才使用 let。
解构赋值
解构赋值是一种模式匹配,即按照对应位置,对变量进行赋值。即左边的变量会赋予右边对应的值。
如果解构不成功,会左边的变量等于 undefined。
如果解构的值不是 iterator 结构,那也会报错。只要具备 Iterator 接口,都可以用数组的方式来进行解构。
解构赋值允许指定默认值。1.只有默认值是 undefined 的时候,默认值才会生效。比如 let[x = 1] = [undefinde] x 还是一个 undefined。2.默认是可以是其他变量,但是需要变量已经声明。
对象的解构赋值是不按次序,按照属性名来进行取值。真正赋值的是对象的属性值,而不是对象的属性名。
对象的解构赋值也可以有默认值。
字符串也可以进行解构赋值,是字符串变转换成一个类似数组的对象。
解构赋值的用途
-
变量互相交换
[x, y] = [y, x]; -
从函数返回多个值,比如返回一个函数,然后解构一下。
-
定义函数参数
function f([x, y, z]) { ... } f([1, 2, 3]); -
提取 JSON 数据。
-
函数参数的默认值。
-
遍历 map 结构。
-
输入模块的指定方法,常用。
数值部分
二进制和八进制
ES6 新增二进制 和 八进制数值的写法。分别是 0b(或者0B 表示)和0o(或者 0O)表示。
Number.isFinite() 和 Number.isNaN()
isFinite 用来检查一个数值是否为有限的(finite),这个方法参数不是数值,一律返回 false。isNaN 用来检查一个是否为 NaN。
Number.parseInt(),Number.parseFloat()
parseInt() 函数可解析一个字符串,并返回一个整数。parseFloat() 函数可解析一个字符串,并返回一个浮点数
其实就是把parseFloat和parseInt的方法从全局移到 Number 对象上面。减少全局方法。
Number.isInteger
Number.isInteger 判断一个数值是否为整数。非数字直接返回 false。
如果数字超出了 53 个二进制位的精度或者数值的绝对值小于Number.MIN_VALUE (5E-324) Number.isInteger可能会误判。
如果对数值精度要求较高,不建议使用 Number.isInteger。
Number.EPSILON
Number.EPSILON是一个极小的常量,表示 1 与大于 1 的最小浮点数之间的差。Number.EPSILON 是 JavaScript 能够表示的最小精度。
作用是可以用来设置“能够接受的误差范围”。比Number.EPSILON 小的话,意义不大。
Number.isSafeInteger()
ES6 引入了 Number.MAX_SAFE_INTEGER(表示js能表示最大的数2^53) 和 Number.MIN_SAFE_INTEGER(表示js能表示最大的数-2^53),数值在这个范围就是安全范围。超过就不能精准表示了。
Number.isSafeInteger()是用来判断一个整数是否在落在安全范围。如果是非数值返回 false,如果数值大于 Number.MAX_SAFE_INTEGER 和小于 Number.MIN_SAFE_INTEGER 都会返回 false。
Math.trunc
Math.trunc 方法用于去除一个数的小数部分,返回整数部分。对于非数值,先使用 Number 方法转换成数值。空值和无法截取的整数的值,返回 NaN。
Math.sign
Math.sign 方法用来判断一个数到底是正数,负数,还是零。
它会返回五种值。 参数为正数,返回+1. 参数为负数,返回-1. 参数为 0,返回 0. 参数为-0,返回-0. 其他值,返回 NaN。
Math.cbrt()
Math.cbrt()方法计算一个数的立方根。非数值使用 Number 方法将其转为数值。 Math.cbrt(27)返回 3
Math.clz32()
Math.clz32()方法将参数转为 32 位无符号整数的形式,返回返回这个 32 位值里面有多个个 0.
Math.imul
Math.imul 方法返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。
Math.hypot
Math.hypot 方法放回所有参数的平方和的平方根。如果参数不是数值,返回NaN。
比如Math.hypot(3, 4) 33 + 44 = 25,25 的平方根是 5。
对数方法
这几个方法不知道用来干啥,先记录一波先。
- Math.exemp1(x)返回ex - 1,即Math.exp(x) - 1。
- Math.log1p(x)方法返回1 + x的自然对数,即Math.log(1 + x)。如果x小于-1,返回NaN。
- Math.log10(x)返回以 10 为底的x的对数。如果x小于 0,则返回 NaN。
- Math.log2(x)返回以 2 为底的x的对数。如果x小于 0,则返回 NaN。
双曲函数方法
感觉普通开发中用不上,动画上可以。 Math.sinh(x) 返回x的双曲正弦(hyperbolic sine) Math.cosh(x) 返回x的双曲余弦(hyperbolic cosine) Math.tanh(x) 返回x的双曲正切(hyperbolic tangent) Math.asinh(x) 返回x的反双曲正弦(inverse hyperbolic sine) Math.acosh(x) 返回x的反双曲余弦(inverse hyperbolic cosine) Math.atanh(x) 返回x的反双曲正切(inverse hyperbolic tangent)
指数运算
ES6 新增指数运算符(**),这个运算符是从由右边开始计算的。
比以前的 Math.pow(x,y)要好不少,** 更直观一点。
字符串
字符的 Unicode 表示法
ES6 加强了对 Unicode 的支持,允许采用\uxxxx 形式表示一个字符,其中 xxxx 表示字符的 Unicode 码点。
但是,这种表示法只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。
字符串的遍历器接口
ES6 为字符串添加了遍历器接口,使得字符串可以被 for...of 循环遍历。可以识别大于 0xFFFF的码点。
模板字符串
模板字符串是增强版的字符串,用反引号(`)标识,它可以当做普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。
大括号里面甚至能调用函数。
fromCodePoint
ES5提供 String.fromCharCode 方法,用于从 Unicode 码点返回对应字符,但是这个方法不能识别码点大于0xFFFF 的字符。
ES6提供了 String.fromCodePoint 方法,可以识别大于 0xFFFF 的字符,弥补了 String.FromCharCode 的不足。
raw
该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,往往用于模板字符串的处理方法。
codePointAt
该方法能够正确处理 4 个字节存储的字符,返回一个字符的码点。
可使用该方法测试一个字符石油两个还是四个字节组成。
normalize
用来将字符的不同表示方法统一为同样的形式,这称为 Unicode 正规化。
includes,startsWith,endsWith
includes:返回布尔值,表示是否找到了参数字符串。
startsWith:返回布尔值,表示参数字符串是否在原字符的头部。
endsWith:返回布尔值,表示参数字符串是否在原字符串的尾部。
都支持第二个参数,表示开始搜索的位置。
repeat
返回一个新字符串,表示将原字符串重复 n 次。
如果参数是小数,会被取整。
如果是负数或 infinity,会报错。
padStart,padEnd
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会再头部或尾部补全。
padStart 用于头部补全。
padEnd 用于尾部补全。
接受两个参数,第一个是字符串补全生效最大长度,第二个参数是用来补全的字符串。
trimStart,trimEnd
ES2019新增两个字符串空格消除方法。跟 trim 一致。只不过 trimStart 消除字符串头部的空格,trimEnd 消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串。
函数
函数参数的默认值
ES6 运行函数设置默认值,写在参数定义后面。
函数参数默认值可以和解构赋值的默认值结合起来使用。
函数参数的默认值一般写在尾部。
指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length属性将失真。
利用函数默认值,可以指定某一个参数不得省略,如果省略就抛出一个错误。
rest 参数
用于获取函数的多余参数,这样子就不需要使用 arguments 对象了。
严格模式
ES 216 开始,规定函数参数使用了默认值,解构赋值,或者扩展运算符,那么函数内部就不能显式的设定为严格模式,否则报错。
name属性
函数的name 属性,返回该函数的函数名。
箭头函数
允许使用箭头(=>)定义函数。
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用 return 语句返回。
注意点
- 函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
- 不可以当做构造函数,也就是说,不可以使用 new 命令,否则会抛出一个错误。
- 不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以使用 rest 参数代替。
- 不可以使用yield 命令,因此箭头函数不能用作 Generator 函数。
数组
扩展运算符(...)
含义
扩展运算符是三个点(...),作用是将一个数组转为用逗号分隔的参数序列。
主要用于函数调用。
可以使用扩展运算符,替换 apply 方法,将数组转为函数的参数了。
应用
-
复制数组,深拷贝一个数组。
-
合并数组,浅拷贝一个数组。
-
与解构赋值结合,生成数组。
const [first, ...rest] = [1, 2, 3, 4, 5]; first // 1 rest // [2, 3, 4, 5] -
使用扩展运算符将字符串转为真正的数组。
-
对于任何定义了遍历器(Iterator)接口的对象,都可以用扩展运算符转为真正的数组。
From 方法
用于将类对象转为真正的数组:类似数组的对象和可遍历(iterable)的对象。
of 方法
用于将一组值,转换为数组。用来替换数组构造函数 Array()的不足。
###copyWithin 方法
在当前数组内部,将指定位置的成员复制到其他位置,然后返回当前数组。
接收三个参数
target(必需):从该位置开始替换数据。如果是负值,表示倒数。
start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示从末尾开始计算。
end (可选):到该位置钱停止读取数据,默认等于数组长度。如果为负值,表示从末尾开始计算。
find 方法 和 findIndex 方法
find 找出第一个符合条件的数组成员,它的参数是一个回调函数,所有成员依次执行该回调函数,知道你找出第一个返回值为 true 的成员,然后返回该成员。如果没有符合条件的成员,则返回 undefined。
fundIndex 跟 find 雷士,返回第一个符合成员的数组下标,如果所有的成员都不符合,则返回-1。
fill 方法
使用给定值,填充一个数组。可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
entries(),keys(),values()
都是用于遍历数数组,返回一个遍历器对象,其中:
entries 是键值对的遍历。
keys是键名的遍历。
values 是键值的遍历。
includes 方法
返回一个布尔值,表示某个数组是否包含给定的值,与字符串的 includes 方法类似。
该方法第一个参数是搜索值,第二个是起始位置(可选),默认 0。
flat,flatMap
flat 用于将嵌套的数组‘拉平’,变成一维数组。该方法返回一个新数组,对原数据没有影响。
flat 可以接受参数,表示拉平嵌套的多少层。默认是 1。如果想要都转成一维数组,可以用 Infinity 关键字作为参数。
flatMap 方法对原数组的每个成员执行一个函数,然后对返回值组成的数组执行 flat 方法。该方法返回一个新数组,不改变原数组。
对象的扩展和新增方法
扩展
属性的简洁表示
- 可以直接把一个变量和函数写到大括号里面,作为对象的属性和方法。
- 使用名字加括号的方式替代方法名:函数的的方式。
属性名的表达式
ES6 可以使用表达式作为对象的属性名,把表达式放到括号内。
方法的name 属性
函数的 name属性,返回函数名,对象方法也是函数,因此,也有 name 属性。
有两种特殊情况:bind 方法创造的函数,name 属性返回 bound 加上原函数的名字;Function 构造函数创造的函数,name 属性返回 anonymous。
属性的可枚举和遍历
对象的每个属性都有一个描述对象(Descriprot),用来控制该属性的行为。Object.getOwnPropertyDescriptor 方法可以获取该属性的描述对象。
有四个操作会忽略enumerable为false的属性。
for...in循环:只遍历对象自身的和继承的可枚举的属性。Object.keys():返回对象自身的所有可枚举的属性的键名。JSON.stringify():只串行化对象自身的可枚举的属性。Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
属性的遍历
- for...in 循环遍历对象自身的和继承的可枚举属性(不含 Symbol属性)
- Object.keys 返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
- Object.getOwnPropertyNames(obj)返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
- Object.getOwnPropertySymbols 返回一个数组,包含对象自身的所有 Symbol 属性的键名。
- Reflect.ownKeys 返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
super 关键字
super,指向当前对象的原型对象。只能用在对象的方法之中,用在其他地方都会报错。
对象的扩展运算符
ES2018 将扩展运算符(...)引入对象。
对象的解构赋值用于从一个对象取值,分配到指定的对象上面。
扩展运算符用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。
属性的新增方法
is 方法
is 方法用来比较两个值是否相等,解决了严格比较运算符(===)的的 +0 -0 和 NaN 问题。
assign
用于对象合并,将元对象的可枚举属性,复制到目标对象。第一个参数是目标对象,后面的参数都是源对象。
注意点
1.Object.assign 实行的是浅拷贝,如果源对象的某个属性是对象,那目标对象得到的是这个对象的引用。
2.如果合并过程中遇到同名属性,使用后面的属性替换前面的。
3.可以用来处理数组,但是会把数组视为对象。
4.assign 只能进行值复制,如果是一个取值函数,那么将求值后再复制。
常见用途
-
为对象添加属性
-
为对象添加方法
-
克隆对象
-
合并多个对象
-
为属性指定默认值
getOwnPropertyDescriptors方法
Object.getOwnPropertyDescriptors()方法,返回指定对象所有自身属性(非继承属性)的描述对象。
__ proto __属性,Object.setPrototypeOf(),Object.getPrototypeOf()
__proto__属性(前后各两个下划线),用来读取或设置当前对象的原型对象(prototype)。
是内部属性,不是正式对外 API,所有不建议使用。
setPrototypeOf 方法的作用与__proto__相同,用来设置一个对象的原型对象(prototype),返回参数对象本身。
getPrototypeOf 方法用于读取一个原型对象。
Object.keys(),Object.values(),Object.entries()
keys 方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键名。
values 方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值。
entries 方法返回一个数组,成员是参数对象的(不含继承的)所有可遍历键值对数组。
fromEntries
该方法是 Object.entries的逆操作,用于将一个键值对数组转为对象。
该方法主要目的是将键值对的数据结构还原为对象,特别合适将 Map 结构转为对象。
Pomise
定义
Promise是一种异步编程解决方案,比回调函数和事件更合理和强大。
Promise 简单来说是一个容器,保存了未来才会结束事件的结果。
promise 对象的两个特点。
1.对象状态不受外部影响。promise 的三种状态: pending(进行中),fulfilled(完成),rejected(已失败)。只有异步操作的结果可以决定当前的状态,其它操作都不可改变。
2.一旦状态改变,就不会再变。任何时候都可以得到这个结果,不管是是 pending 变成 fulfilled还是 pending 变为 rejected。只要这两种情况发生。就不会再变。
基本用法
Promise 对象是一个构造函数,用来生成 Promise 实例。构造函数可以接受两个参数,分别是 resolve函数 和 reject函数。reject 参数是可选的。
resolve 函数的作用是,将 Promise 对象从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject 函数的作用是,将 Promise 对象从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
Promise 新建后会立即执行,然后将在当前脚本的所有同步任务执行完才会执行 then 方法的回调函数。
then 方法
then 方法定义在原型对象 Promise.prototype 上。then 返回的是一个新的Promise实例。因此可以采用链式调用的方法。在 then 方法后面再调用另一个 then 方法。
catch 方法
catch方法用于指定发生错误时的回调函数。
如果 Promise 对象的状态是 rejected会调用 catch 方法指定的回调函数。另外,then 方法指定好的回调函数如果运行中抛出错误,也会被 catch 方法捕获。
Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。
finally方法 ES018 引入
finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。
finally 犯法的回调函数不接受任何参数,finally 的操作跟状态无关,不依赖 Promise 的执行结果。
all 方法。
all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。该方法接受一个数组作为参数。可以不是数组,但需要有 Iterator 接口,且返回成员都是 Promise 实例。
该方法的状态分为两种情况
1.所有参数的 Promise 实例状态都变成 fulfilled ,然后新 Promise 实例的状态变成 fulfilled,然后所有的参数返回值会组成一个数组,传给新Promise 实例的回调函数。
2.只要参数中有一个 Promise 状态变成 rejected,则新 Promise 实例的状态变成 rejected,此时第一个被 rejected 的实例的返回值,会传递给新Promise 实例的回调函数。
race 方法
race 方法也是将多个Promise实例,包装成一个新的 Promise 实例。
race 方法的参数跟 all 方法一样。不过区别在于 race 方法参数中的任一 Promise 实例率先改变状态,race 方法的新实例状态也会改变,并且接受率先改变的 Promise 实例的返回值。传递给 新实例的回调函数。
allSettled方法 ES2020 引入
allSettled 方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例,只有等所有这些参数实例都返回结果,不管是 fulfilled 还是 rejected ,包装实例才会结束。
resolve 方法
resolve 方法将现有对象转为 Promise 对象。
根据参数不同,分成四种情况
-
参数是Promise 对象,那么原封不动返回这个实例。
-
参数是thenable 对象,thenable 对象指的是具有 then 方法的对象。会降这个对象直接转为 Promise 对象,然后执行里面的 then 方法。
-
参数不具有 then 方法或者不是对象,返回贵新的 Promise 对象,状态 Wieresolve。
-
无参数,直接返回一个 resolve 状态的 Promise 对象。
reject 方法
reject方法也会返回一个新的 Promise 实例,该实例的状态为 rejected。
Promise 应用
1.加载图片
2.发送请求
3.Generator 函数与 Promise 的结合。
使用 Generator 函数管理流程,遇到异步操作的时候,通常返回故意而 Promise 对象。
async
定义
简单来说就是 Generator 函数的语法糖。
async 函数就是将 Generator 函数的星号(*)替换成 async,将 yield 替换成 await,仅此而已。
改进点
-
内置执行器,不需要使用 next方法,直接调用即可。
-
更好的语义,比起星号和 yield,async 表示函数有异步操作,await 表示紧跟在后面的表达式需要等待结果。
-
更广的适用性。await 命令后面可以是 Promise 对象和原始类型的值。
-
返回值是 Promise。
基本用法
async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
语法
返回 Promise 对象
async函数返回一个 Promise 对象。
async函数内部 return 语句返回的值,会成为 then 方法回调函数的参数。
await 命令
await 命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。如果是一个 thenable对象,那么 await 会将其等同于 Promise 对象。
错误处理
如果 await 后面的异步操作出错,那么等同于 async 函数返回的 Promise 对象被 reject。
async 函数的实现原理
async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里面。
async function fn(args) {
// ...
}
// 等同于
function fn(args) {
return spawn(function* () {
// ...
});
}
Iterator
定义
迭代器是被设计用于迭代的对象,带有特定接口。所有的迭代器对象都拥有 next()方法,会返回一个结果对象。该结果对象有两个属性: 对应下一个值的 value,以及一个布尔类型的 done,其值为 true 时表示没有更多值可供使用。
默认的 Iterator 接口部署在数据结构的 symbol.iterator 属性。也就是说,一个数据结构只要具有 symbol.iterator 属性,就可以认为是“可遍历的”。
原生具有 Iterrator 接口的数据结构如下。
-
Array
-
Map
-
Set
-
String
-
TypedArray
-
函数的 arguments 对象
-
NodeList 对象
调用 Iterator 接口的场合
-
结构赋值
-
(...)扩展运算符
-
yield*
-
其它场合,只要调用的数组作为参数的场合都用到了。比如 for...of ,Array.from, Map()看,Set()。
字符串的 Iterator 接口
字符串是一个类似数组的对象,也原生具有 Iterator 接口。
集合的迭代器
数组,Map 和 Set 这三种都用如下三个内置的迭代器。
entries 返回一个包含键值对的迭代器。
values 返回一个包含集合中的值的迭代器。
keys 返回一个包含集合中的键的迭代器。
Symbol
定义
ES6 引入一种原始数据类型 symbol。表示独一无二uerde 值。它是 JavaScript 第七中数据类型。
Symbol 的值是通过 Symbol 函数生成。Symbol 的值不能与其它类型的值进行运算,会报错。可以转换成布尔值和字符串。
description
创建 Symbol 的时候,可以添加描述。例如:const sym = Symbol('foo'); foo 就是描述。
可以使用转换字符串的方式得到描述。ES2019 提供了description方法,直接返回 Symbol 描述。
作为属性名的 Symbol
由于每一个 Symbol 值都是不相等的。所有可以把 Symbol 作为标识符,用于对象的属性名。
需要注意不能使用点(.)运算符,不然的话标识符算是一个字符串而不是一个 Symbol 的值。
应用:
-
可以使用 Symbol 的值,来消除魔术字符串。魔术字符串指的是,与代码形成“强耦合”。
-
模块的 SIngleton 模式。当我们使用模块 module 的时候,我们把实例放到顶层对象 global 上面,但是这回导致一个问题,全局的变量是可改写的,一旦改写,我们的 module 就会失真。这时候可以使用 Symbol来解决这个问题。
属性名的遍历
使用Object.getOwnPropertySymbols()可以获得所有的 Symbol 属性名。
使用常规的 for循环,Object.keys()等没办法获取 Symbol 值的属性名。所有我们可以利用这个特性,写成了非私有的内部方法。
Symbol.for(),Symbol.keyFor()
Symbol.for 重复生成同一个 Symbol 的值,接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。
Symbol.keyFor()方法返回一个已登记的 Symbol 类型值的 key。
内置的Symbol 值
hasInstance
指向一个内部方法。当其他对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法。
inConcatSpreadalbe
等于一个布尔值,表示该对象用于 Array.prototype.concat时,是否可以展开。
species
指向一个构造函数。创建衍生对象时,会使用该属性。
match
指向一个函数。当执行 str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值。
replace
指向一个方法。当该对象被 String.prototype.replace 方法调用时,会返回该方法的返回值。
search
指向一个方法。当该对象被 String.prototype.search 方法调用时,会返回该方法的返回值。
split
指向一个方法。当该对象被 String.prototype.split 方法调用时,会返回该方法的返回值。
iterator
指向该对象的默认遍历器方法。
toPrimitive
指向一个方法。该对象被转为原始雷士的值时,会调用这个方法,返回该对象对应的原始类型值。
Symbol.toPrimitive 被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式。
- Number:该场合需要转成数值
- String:该场合需要转成字符串
- Default:该场合可以转成数值,也可以转成字符串
toStringTag
指向一个方法。在该对象上面调Object.portotype.toString 方法时,如果这个属性存在,它的返回值会出现在 toString 方法返回的字符串之中,表示对象的类型。
uncosopables
指向一个对象,该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。
Proxy
定义
Proxy 用于修改某些默认行为,等同于在语言层面做出修改,所以属于一种“元编程”。
在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
var proxy = new Proxy(target, handler);
Proxy 对象的所有用法,都是上面这种形式,不同的只是 handle 参数的写法。其中,new Proxy()表示生成一个 Proxy 实例,target 参数表示所哟啊拦截的目标对象,handle 参数也是一个对象,用来定制拦截行为。
Proxy实例方法
get
get 方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象,属性名和 proxy 实例本身,其中最后一个参数可选。
set
set 方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象,属性名,属性值和 proxy 实例本身,其中最后一个参数可选。
apply
apply 方法拦截函数的调用,call 和 apply 操作。
apply 方法可以接受三个参数,分别是目标对象,目标对象的上下文对象和目标对象的参数数组。
has
has 方法用来拦截 HasProperty 操作,即判断对象是否具有某个属性时,这个方法会生效。典型的操作就是 in 运算符。
has 方法可以接受两个参数,分别是目标对象,需查询的属性名。
construct
construct 方法用于拦截 new 命令。
construct 方法可以接受三个参数。
target:目标对象。
args: 构造函数的参数对象。
newTarget:创造实例对象,new 命令作用的构造函数。
deleteProperty
deleteProperty 方法用于拦截 delete 操作,如果这个方法抛出错误或者返回 false,当前属性就无法被 delete 命令删除。
defineProperty
defineProperty 方法拦截了 Object.defineProperty 操作。
getOwnPropertyDescriptor
getOwnPropertyDescriptor 方法拦截Object.getOwnPropertyDescriptor(),返回一个属性描述对象或者undefined。
getPrototypeOf
getPrototypeOf方法主要用来拦截获取对象原型。
Object.prototype.__proto__Object.prototype.isPrototypeOf()Object.getPrototypeOf()Reflect.getPrototypeOf()instanceof
isExtensible
isExtensible方法拦截 Object.isExtensible 操作。
ownKeys
ownKeys()方法用来拦截对象自身属性的读取操作。具体来说,拦截以下操作。
Object.getOwnPropertyNames()Object.getOwnPropertySymbols()Object.keys()for...in循环
preventExtensions
preventExtensions()方法拦截Object.preventExtensions()。该方法必须返回一个布尔值,否则会被自动转为布尔值。
setPrototypOf
setPrototypOf方法用来拦截 Object.setPrototypeOf 方法。
Proxy.revocable
Proxy.revocable()方法返回一个对象,该对象的proxy属性是Proxy实例,revoke属性是一个函数,可以取消Proxy实例。
Proxy 的 this 问题
目标对象内部的this关键字会指向 Proxy 代理。
Set 和 Map
Set
定义
Set类似数组,但是成员的值都是唯一的,没有重复的值。
Set 本身是一个构造函数,用来生成 Set 数据结构。
属性和方法
属性有两个:
-
Set.prototype.constructor 构造函数,默认就是 set 函数。
-
Set.prototype.size 返回 Set 实例的成员总数。
方法有四个:
-
add(value):添加某个值,返回 Set 结构本身。
-
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
-
has(value):返回一个布尔值,表示该值是否为 Set的成员。
-
clear:清楚所有成员,没有返回值。
遍历操作
keys():返回键名的遍历器
values():返回键值的遍历器
entries()返回键值对的遍历器
forEach() 使用回调函数遍历每个成员
Map
定义:
类似对象,也是键值对集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键。
属性和方法
size 属性返回 Map 结构的成员总数。
set(key,value) 方法,设置键名key 对应的键值为 value,然后返回整个 Map 结构。如果 key已经有值,则键值会被更新,否则就新生成该建。
get 方法读取 key对应的键值,如果找不到 key,返回 undefined。
has 方法返回一个布尔值,表示某个键是否在当前的 Map 对象之中。
delete 方法删除某个键,返回 true。如果删除失败,返回 false。
clear 方法清除所有成员,没有返回值。
遍历方法
keys: 返回键名的遍历器。
values:返回键值的遍历器
entries:返回所有成员的遍历器。
forEach:遍历 Map 的所有成员。
和其它数据结构互相转换
- Map 转为数组
Map 转为数组最方便的方法,就是使用扩展运算符(...)
- 数组转为 Map
将数组传入 Map 构造函数,就可以转为 Map。
- Map 转为对象
如果所有的 Map 的键都是字符串,
- 对象转为 Map
对象转为 Map 可以通过 Object.entries()
- Map 转 JSON
Map 转为 JSON 要区分两种情况。一种情况是,Map 的键名都是字符串,这时可以选择转为对象 JSON。
另一种情况是,Map 的键名有非字符串,这时可以选择转为数组 JSON。
- JSON 转 Map
JSON 转为 Map,正常情况下,所有键名都是字符串。
WeakSet
定义:
和 Set 类似,也是不重复的值的集合。
区别在于:
1.WeakSet 的成员只能是对象,而不能是其他类型的值。
2.WeakSet的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用。
方法
add :向 WeakSet 实例添加一个新成员。
delete(value):清除 WeakSet 实例的指定成员。
has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例之中。
WeakMap
定义
WeakMap 结构和 Map 结构类似,也是用于生成键值对的集合。
区别
1.WeakMap 只接受对象作为键名(null 除外),不接受其他类型的值作为键名。
2其次,WeakMap的键名所指向的对象,不计入垃圾回收机制。
语法
WeakMap 比较特殊:
- 没有遍历操作
- 没有清除方法
- 只有 get,set,has,delete 四个方法。
字符串
正则表达式
模板字符串
poxy
对象
Generator
定义:
Generator 函数是一种异步编程解决方案,语法行为和传统函数完全不同。
Generator 函数和普通函数的区别:
-
函数关键字与函数名之间有一个星号
-
函数体内部使用 yield 表达式。定义不同的内部 状态。
Generator 调用方法与普通函数一样,也是函数名后面加上一对圆括号。返回的是执行内部状态的指针对象。然后使用遍历器对象的 next方法,使得指针移下一个状态。
调用 next 方法,会返回一个对象,其中 value 属性返回 yield 表达式的值,done 属性是 true。如果遍历完毕,next 方法返回的 value 值是 undefined。done 属性返回 false。
yield 表达式
由于 Generator 函数返回的遍历器对象,只有调用 next 方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield 表达式就是暂停标志。
遍历器对象 next 方法的运行逻辑如下。
-
遇到 yield 表达式,就暂停执行后面的操作,并将紧跟在 yield 后面的那个表达式的值,作为返回对象的 value 属性值。
-
下一次调用 next 方法时,再继续往下执行,直到遇到下一个 yield 表达式。
-
如果没有再遇到新的 yield 表达式,就一直运行到函数结束,直到 return 语句为止,并将 return 语句后面的表达式的值,作为返回对象的 value 属性值。
-
如果该函数没有 return 语句,则返回对象的 value 属性值为 undefined。
与 Iterator 接口的关系
由于 Generator 函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的 Symbol.itertor属性,从而使得该对象具有 Iterator 接口。
有了 Iterator 接口,就可以使用...运算符遍历了。
Next 方法的参数
yield 表达式本身没有返回值,或者说总是返回 undefined。next 方法可以带一个参数,该参数就会被当做上一个 yield 表达式的返回值。
next 方法可以带参数,也就是说可以通过向函数注入值,从而调整函数的行为。
for...of 循环
使用 for...of 循环可以自动遍历 Generator 函数运行时生成的 Iterator 对象,且此时不再需要调用 next 方法。
同理,扩展运算符(...),解构赋值和 Array.form 方法内部都是遍历器接口。
throw 方法
throw 方法可以在函数体外抛出错误,然后在 Generator 函数体内捕获。
throw 方法可以接受一个参数,会被 catch 语句接收,建议抛出 Error 对象的实例。
return方法
rerun 方法,可以返回给定的值,并且终结遍历 Generator 函数。
return 方法可以有参数,返回值的 value属性就是传递的参数,如果没有的话 value 属性为 undefined。
作为对象属性的 Generator 函数
如果对象属性是 Generator 函数可以简写为:
let obj = {
* myGeneratorMethod() {
···
}
};
等价于:
let obj = {
myGeneratorMethod: function* () {
// ···
}
};
Generator 应用
-
用来处理异步操作,改写回调函数
-
控制流管理
-
利用 Generator 函数,可以在任意对象上部署 Iterator 接口。
-
作为一种数据结构。