阮一峰《ECMAScript 6 入门》 学习摘要

282 阅读8分钟

学习文档为阮一峰老师的《ECMAScript 6 入门》

这本书是月初看的,折腾好久到上周才看完,今天才来匆匆整理一下。本来一开始说是复习 ES6 的,学到一半才发现自己以前学了个假的 ES6,以前只是听了一些皮毛,勉强用一用,对内里几无了解。而且内容比我想象中的多太多了,远不是一篇文章能总结的,所以就先摘一个目录,暂时告一个段落。之后再针对每一项做专题梳理。书也还要再多读几遍才行。


ES6 虽然平时也用到,不过都很浅,常用 let、const、箭头函数、扩展运算符这些,其他不常用,promise 虽然看了很多遍,但用得少也忘得差不多了,偶尔碰到还有点怵。这次就再来复习一遍 ES6。
本书内容较多,一天可能完不成,又不愿拆成几节,故几天的合在一起吧,特别重要的可以单拎出来。争取本周内完成。

长久以来的一个疑惑:浏览器似乎不太支持 ES6 等新特性,用新语法写的代码最后都要转为 ES5,因此有些疑惑用新语法写会不会带来问题,如兼容不太好等。也许我有点为机器担忧了,以后多尝试写,看看有什么影响和区别吧。

      
  • let 和 const 命令

    const 定义的对象变量只能保证指针不变,并不能保证指向的对象内容不改变,因此可以用 Object.freeze 来冻结对象,使其不可变。

    一个将对象彻底冻结的方法:
      var constantize = (obj) => { 
          Object.freeze(obj);
          Object.keys(obj).forEach( (key, i) => {
          if ( typeof obj[key] === 'object' ) {
              constantize( obj[key] );
              }
          });
       };
    
  •   
  • 变量提升、暂时性死区
  •   
  • 块级作用域

    块级作用域与函数声明

    ES5 不允许在块级作用域声明函数,ES6 允许,但为了减轻对旧代码的影响,对 ES6 浏览器环境做了特别规定。因此考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

    顶层对象的属性

    ES5 浏览器环境中顶层对象指 window 对象,顶层对象的属性和全局和全局变量是等价的,这有很大弊端。因此 ES6 中将它们脱钩,var 沿用旧例,let 等声明的全局变量不再是顶层对象的属性。

  •   
  • 解构赋值、默认值
  •   
  • 字符串扩展
    • 字符的 Unicode 表示法:\uxxxx
    • 遍历器接口
    • 模板字符串:`……${x}……`.trim()
  •   
  • 字符串新增方法
    • String.fromCodePoint():用于从 Unicode 码点返回对应字符
    • String.raw():该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串
    • String.codePointAt()
    • includes(), startsWith(), endsWith()
    • repeat()
    • padStart(),padEnd()
    • trimStart(),trimEnd()
    • replaceAll()
  •   
  • 正则的扩展:u、y、s修饰符;后行断言
  •   
  • 数值的扩展
    • 二进制:0B、八进制:0O
    • 数值分隔符
    • Number.isFinite(), Number.isNaN()
    • Number.isInteger()
    • 安全整数和 Number.isSafeInteger()
    • Math 对象的扩展
    • 安全整数和 Number.isSafeInteger()
  • 函数的扩展
    • 参数默认值
    • 函数的 length 属性:返回没有指定默认值的参数个数
    • rest 参数
    • 函数的 name 属性
    • 箭头函数
    • Math 对象的扩展
    • 安全整数和 Number.isSafeInteger()
    • 尾调用优化:尾调用(Tail Call)是指某个函数的最后一步是调用另一个函数。
  •   
  • 数组的扩展
    • 扩展运算符
    • Array.from()
    • Array.of()
    • copyWithin()
    • 数组实例的 find() 和 findIndex()
    • 数组实例的 fill()
    • 数组实例的 entries(),keys() 和 values()
    • 数组实例的 includes()
    • 数组实例的 flat(),flatMap()
    • Array.prototype.sort() 的排序稳定性
  • 对象的扩展
    • 属性的简洁表示法
    • 属性名表达式
    • 属性的可枚举性和遍历
    • super 关键字
    • 对象的扩展运算符
  • 对象的新增方法
    • Object.is()

      同值相等:与严格比较运算符(===)的行为基本一致。不同之处只有两个:一是 +0 不等于 -0 ,二是 NaN 等于自身。

    • Object.assign() 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)
    • Object.getOwnPropertyDescriptors()
    • Object.keys(),Object.values(),Object.entries()
    • Object.fromEntries()
  • 运算符的扩展
    • 指数运算符:**
    • 链判断运算符:?.
    • Null 判断运算符:??
    • 逻辑赋值运算符:||=、&&=、??=
  • Symbol 类型

    Symbol 函数前不能使用 new 命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。

    • Symbol.prototype.description
    • 作为属性名的 Symbol:以 Symbol 值作为键名,不会被常规方法遍历得到。
    • Object.getOwnPropertySymbols()
    • Reflect.ownKeys()
    • Symbol.for(),Symbol.keyFor()
    • 对象的 Symbol.hasInstance 属性:instanceof
    • 对象的 Symbol.isConcatSpreadable 属性等于一个布尔值,表示该对象用于 Array.prototype.concat() 时,是否可以展开。
    • 对象的 Symbol.species 属性,指向一个构造函数。
    • 对象的 Symbol.match 属性:str.match(myObject)
    • 对象的 Symbol.replace 属性:String.prototype.replace
    • 对象的 Symbol.search 属性:String.prototype.search
    • 对象的 Symbol.split 属性:String.prototype.split
    • 对象的 Symbol.iterator 属性,指向该对象的默认遍历器方法。
    • 对象的 Symbol.toPrimitive 属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
    • 对象的 Symbol.toStringTag 属性
    • 对象的 Symbol.unscopables 属性,指向一个对象。该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。
  • Set 数据结构

    类似于数组,但是成员的值都是唯一的,没有重复的值。

    • Set.prototype.constructor:构造函数,默认就是 Set 函数
    • Set.prototype.size:返回 Set 实例的成员总数
    • Set.prototype.add(value):添加某个值,返回 Set 结构本身
    • Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
    • Set.prototype.has(value):返回一个布尔值,表示该值是否为 Set 的成员。
    • Set.prototype.clear():清除所有成员,没有返回值。
    • Set.prototype.keys():返回键名的遍历器
    • Set.prototype.values():返回键值的遍历器
    • Set.prototype.entries():返回键值对的遍历器
    • Set.prototype.forEach():使用回调函数遍历每个成员
       // 字符串去重方法
        [...new Set('ababbc')].join('')
    
        // 数组去重方法
        [...new Set(array)]
        
        function dedupe(array) {
          return Array.from(new Set(array));
        }
        
        let arr = [3, 5, 2, 2, 5, 5];
        let unique = [...new Set(arr)];
        // [3, 5, 2]
       
    
  • WeakSet 结构

    WeakSet 的成员只能是对象,而不能是其他类型的值。WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用。WeakSet 不可遍历。
    WeakSet 的一个用处,是储存 DOM 节点,而不用担心这些节点从文档移除时,会引发内存泄漏。

  • Map 数据结构

    类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。

    • size 属性
    • Map.prototype.set(key, value)
    • Map.prototype.get(key)
    • Map.prototype.has(key)
    • Map.prototype.delete(key)
    • Map.prototype.clear()
    • Map.prototype.keys():返回键名的遍历器。
    • Map.prototype.values():返回键值的遍历器。
    • Map.prototype.entries():返回所有成员的遍历器。
    • Map.prototype.forEach():遍历 Map 的所有成员。
  • WeakMap 结构

    WeakMap 只接受对象作为键名(null 除外),不接受其他类型的值作为键名。WeakMap 的键名所指向的对象,不计入垃圾回收机制。WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用。
    WeakMap 只有四个方法可用:get()、set()、has()、delete()。

  • WeakRef 对象,用于直接创建对象的弱引用

    WeakRef 实例对象有一个 deref() 方法,如果原始对象存在,该方法返回原始对象;如果原始对象已经被垃圾回收机制清除,该方法返回 undefined。

  • FinalizationRegistry:清理器注册表功能
  • 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 实例
  • Reflect
    • Reflect.apply(target, thisArg, args)
    • Reflect.construct(target, args)
    • Reflect.get(target, name, receiver)
    • Reflect.set(target, name, value, receiver)
    • Reflect.defineProperty(target, name, desc)
    • Reflect.deleteProperty(target, name)
    • Reflect.has(target, name)
    • Reflect.ownKeys(target)
    • Reflect.isExtensible(target)
    • Reflect.preventExtensions(target)
    • Reflect.getOwnPropertyDescriptor(target, name)
    • Reflect.getPrototypeOf(target)
    • Reflect.setPrototypeOf(target, prototype)
  • Promise 对象
    • Promise.prototype.then()
    • Promise.prototype.catch()
    • Promise.prototype.finally()
    • Promise.all()
    • Promise.race()
    • Promise.allSettled()
    • Promise.any()
    • Promise.resolve()
    • Promise.reject()
    • Promise.try()
  • Iterator(遍历器)和 for...of 循环
    • 默认 Iterator 接口:Symbol.iterator
        原生具备 Iterator 接口的数据结构如下:
      • Array
      • Map
      • Set
      • String
      • TypedArray
      • 函数的 arguments 对象
      • NodeList 对象
    • 调用 Iterator 接口的场合
      • 解构赋值
      • 扩展运算符
      • yield*
      • for...of
      • Array.from()
      • Map(), Set(), WeakMap(), WeakSet()(比如`new Map([['a',1],['b',2]])`)
      • Promise.all()
      • Promise.race()
    • 字符串的 Iterator 接口
    • Iterator 接口与 Generator 函数
    • 遍历器对象的 return(),throw()
  • Generator 函数

    Generator 函数是 ES6 提供的一种异步编程解决方案。Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象。

    • yield 表达式
    • yield* 表达式
    • 与 Iterator 接口的关系
    • next 方法的参数
    • for...of 循环
    • Generator.prototype.throw()
    • Generator.prototype.return()
    • Generator 函数的 this
    • Generator 函数的异步应用
  • async 函数
  • Class 的基本语法
    • constructor 方法
    • 取值函数(getter)和存值函数(setter)
    • 属性表达式
    • Class 表达式
    • 静态方法
    • 静态属性
    • 私有方法和私有属性
    • Class 的继承
  • Module 的语法
  • ArrayBuffer
  • 编程风格