我的ES6总结

233 阅读7分钟

阮大ES6入门学习总结

一、let 和 const 命令

  • 块级作用域。
  • for循环,变量设置部分与循环体部分可看成父子作用域。
  • 无变量提升,‘变量提升’形成暂时性死区,同作用域不能重复定义。
  • 自执行函数形成独立作用域写法,可以改成{let}写法。
  • 函数表达式替换声明函数写法。
  • const不变的是数据内存地址。

二、解构赋值

  • 数组按序赋值(也可以已下标为键名,对象形式解构),对象按属性名赋值。
  • 对象解构变量是左边的建值。
const {a} = {a: 1};
// 实际左边是{a: a}的简写, 变量是{a: a}中后面(建值)的a
  • 对象解构可重复取值,属性名对应上。
const {a,a: b, a: c} = {a: 1};
  • 解构赋值可设置默认值,只有解构目标严格等于(===)undefined时才取默认值。
  • 解构赋值不要以{为行首,会解析成块级作用域,可以用()包住整个表达式,其他情况尽量避免使用(),防止出现解构歧义报错。
  • 基本数据类型解构赋值。
  • 函数参数解构赋值,及默认值设置方法。
  • Map对象解构遍历。

三、字符串拓展

  • 字符串遍历for...of
  • 字符串模板写法`${}`包裹内容,{}内为可计算变量。
  • 字符串模板入参函数(标签模板)。
  • includes(x)包含x、startsWith(x)匹配x开始, endsWith(x)匹配x结束,repeat(x)复制x次拼接,padStart(x,y)在开头用y循环补充到x位,padEnd(x,y)在结尾用y循环补充到x位,trimStart()去前空格,trimEnd()去后空格,matchAll()列出所有match。

四、正则拓展

  • 断言匹配。
  • 组名匹配。

五、数值拓展

  • Math.trunc()去掉小数部分,Math.hypot()计算平方和的平方根,**指数运算符。
  • 各种精度处理方法,及Number.isFinite(), Number.isNaN(),Number.parseInt(), Number.parseFloat()移到Number对象上针对数值类型判断。

六、函数拓展

  • rest参数fn(...arg)。
  • 箭头函数,this指向外层this。
  • 参数尾逗号,catch可无参数。

七、数组拓展

  • 扩展运算符...,替换f.apply、str.split(''),有Iterator 接口的对象都可使用:
Number.prototype[Symbol.iterator] = function*() {
  let i = 0;
  let num = this.valueOf();
  while (i < num) {
    yield ++i;
  }
}
console.log([...5]) // [1, 2, 3, 4, 5]
  • a = [...b] || [...a] = b 都能实现a与b之间的深拷贝(a与b本身引用不同),但a与b内部元素是浅拷贝(内部元素引用指向一致)。
  • Array.from()将类数组转化为数组,且可以传入第二个参数与map作用一致。
Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);
  • Array.of()代替 new Array。Array.of()得到的总是参数组成的数组。
  • arr.fill()填充参数为对象时,对象指针一致。
  • 其他实例方法:copyWithin()find()findIndex()entries()keys()values()includes()flat()flatMap(),entries返回一个Generator函数、flat入参数字表示扁平层级(可传Infinity完全扁平)。

八、对象拓展

  • 简洁定义、属性表达式定义。
  • super关键字,指向对象原型对象。
  • ...运算符。
  • es2020新添加:??判断运算符及?.判断连运算符。
  • Object.is()替换===
+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
  • Object.assign()对象属性合并,对象继承。
  • Object.getOwnPropertyDescriptors()获取自身属性描述。
  • __proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()原型属性操作方法。
  • Object.keys(),Object.values(),Object.entries()对象遍历方法,其中Object.entries()是Generator函数。Object.fromEntries()用于map转obj。

九、Symbol

  • undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)之后,javascript的第七种数据类型,用来创建唯一变量,可用作对象属性名。不是私有属性,不能被for...in、for...of遍历到。
  • Symbol.prototype.description获取定义Symbol定义时的参数字符串。
  • Object.getOwnPropertySymbols()获取Symbol属性。
  • Symbol.for():可理解成注册全局唯一变量。
  • Symbol.keyFor():获取已注册变量的入参字符串。
  • 内置Symbol值:

Symbol.hasInstance:改变instanceof返回。

Symbol.isConcatSpreadable:concat是否可展开。

Symbol.species:指定父级链开始计算instanceof。

Symbol.match:改变str.match返回。

Symbol.replace:改变str.replace返回。

Symbol.search:改变str.search返回。

Symbol.split:改变str.split返回。

Symbol.iterator:改变默认遍历返回。

Symbol.toPrimitive:根据数据类型需求返回不同值(想到了经典问题a==1&&a==2成立)。

let obj = {
  [Symbol.toPrimitive](hint) {
    switch (hint) {
      case 'number':
        return 123;
      case 'string':
        return 'str';
      case 'default':
        return 'default';
      default:
        throw new Error();
     }
   }
};

2 * obj // 246
3 + obj // '3default'
obj == 'default' // true
String(obj) // 'str'

Symbol.toStringTag:修改数据toString返回的空格后字符串。

Symbol.unscopables:with环境排除属性数组

十、Set与Map数据结构

  • Set数组,字符串去重;Map非字符串属性对象。
  • Set.prototype.sizeSet.prototype.add(value)Set.prototype.delete(value)Set.prototype.has(value)Set.prototype.clear()
  • Map.prototype.sizeMap.prototype.set(key, value)Map.prototype.get(key)Map.prototype.has(key)Map.prototype.delete(key)Map.prototype.clear(key),map.set可以链调。
  • WeakSet、WeakMap:都可以理解为键名只能是对象,键名所指对象不会计入垃圾回收机制。

十一、Proxy数据代理,Reflect对象

  • Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
  • Proxy 实例的方法:

get(target, propKey, receiver):拦截对象属性的读取。

set(target, propKey, value, receiver):拦截对象属性的设置。

has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。

deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。

ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。

getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。

defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。

preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。

getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。

isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。

setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。

apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。

construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。

  • Proxy.revocable():创建一个可取消的Proxy实例。
  • Proxy实例的this指向Proxy,而非实例对象本身。
  • Reflect对象的方法与Proxy对象的方法一一对应。
  • 使用 Proxy、Reflect 实现观察者模式。

十二、Promise 对象

  • 状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。
  • 原型属性Promise.prototype.then()、Promise.prototype.catch()、Promise.prototype.finally()
  • Promise.all():所有请求得到结果,或者某个请求报错则结束。
  • Promise.race():某个请求得到结果,或者某个请求报错则结束。
  • Promise.allSettled():所有请求结束则结束。
  • Promise.resolve()then接收、Promise.resolve()catch接收。

十三、Iterator 和 for...of 循环

  • 数据原型添加[Symbol.iterator]接口,即可用for...of遍历、...语法糖解析。
  • Array、Map、Set、String、TypedArray、函数的 arguments 对象、NodeList 对象自带Iterator接口。
  • Iterator接口,本身可以理解成Generator函数next()方法获取的数据。

十四、Generator函数

  • js异步处理方法
  • 一般在传统函数function后紧跟*,函数内用yield来处理异步
  • next()、throw()、return()可以理解替换yield
function* gen() {
  yield  123 + 456;
}
  • yield*用来拆解Generator内部的Generator
  • this处理,与配合new使用方法
function* gen() {
  this.a = 1;
  yield this.b = 2;
  yield this.c = 3;
}
function F() {
  return gen.call(gen.prototype);
}
var f = new F();
  • Thunk 函数:用来替换计算表达式。
  • co 模块:用于 Generator 函数的自动执行。

十五、async 函数

  • async函数实际是 Generator 函数的语法糖,结果返回的是Promise对象。
  • 更简洁、语义的实现异步调用,不好处理异常

十六、类Class

  • 可理解成构造函数语法糖,更好的实现继承
  • 类的所有方法都定义在类的prototype属性上面
  • 类的内部所有定义的方法,都是不可枚举的
  • 与 ES5 一样,在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
  • 类的方法内部如果含有this,它默认指向类的实例
  • Class 可以通过extends关键字实现继承
  • Object.getPrototypeOf方法可以用来从子类上获取父类。
  • 子类的构造函数必须执行一次super函数,super()在相当于父类.prototype.constructor.call(this)
  • 子类的__proto__属性,表示构造函数的继承,总是指向父类
  • 子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性