ES6语法第一次学习

-----------------------第一次:概读,了解重点知识,归纳总结-------------------------------

变量

  • ES5的两种声明变量的方法: var function
    • ES5中浏览器的顶层对象window的属性包含全局变量.比如 window.a = 2; a = 1; window.a //1;
    • 顶层对象window
  • ES6的六种声明变量的方法: var function const let import class
    • ES6中把window的属性与变量let,const进行了分离
    • 顶层对象global,通过垫片库system.global拿到

常量const

  • 1.常量不能更改值,必须在声明时就赋值,不提升解析,不能未声明就赋值,不能同作用域重复.
  • 2.常量不是不能改变值的属性,而是不能改变对应内存的地址.比如对象或者数组.
  • 如果想让对象和属性都完全冻结,不能使用属性或者方法,可以使用object.freeze({}),甚至也可以把属性也冻结

变量let

  • 1.let支持块级作用域
    即:let声明的变量只在该代码块中生效,其他作用域无法调用,但是全局变量let可以在次级作用域中继承.
    • //for循环中var和let的区别
    • //变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。
    • //变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量.
  • 2.let没有变量提升,也就是没有预解析,输出报错(不存在),而var输出undefined
    • let变量在没有声明之前就赋值,检测会报错,也叫暂时性死区 没有声明变量都不可用
  • 3.let变量命名在同级作用域中不能重复
  • 4.块级作用域解释
    • ES5 只有全局作用域和函数作用域,内层变量可能会覆盖外层变量
    • ES6 每个大括号{}都代表一个let的块级作用域, 外层无法读取内部变量,但是内部变量可以与外部变量重名.
      • 还可以实现多层嵌套{{{let ...}}}
      • 自执行函数(function(){var ...})可以简写为一个let的块级作用域{let ...}
      • 在块级作用域中函数声明然后调用,es6会报错.尽量避免使用函数声明 function(){} 建议使用声明式函数let fn = function(){}

变量的解构赋值

模式匹配

  • 数组/对象/字符串/数值/布尔值/函数参数
    • 只要等号两边的模式相同,左边的变量就会被赋予对应的值
    • 另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组
  • 数组
    • 1.解构不成功,变量的值就等于undefined 而..n对应的元素不存在,则是[]
    • 2.对于无法遍历或者不相同的结构是无法解构赋值的.
    • 3.解构赋值可以有默认值,但必须该元素对应的赋值是undefined(也可以是没写),否则就是赋值
      • 默认值可以是其他解构赋值的变量,但必须先声明,否则报错
  • 对象
    • 1.数组的解构赋值必须是按照顺序赋值,而对象则必须按照变量名与属性名相同赋值
    • 2.对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
    •   {属性:属性值} 属性是匹配的模式,属性值才是被赋值 {属性值} 写一个也可以赋值,表示的属性值与属性同名
      复制代码
    • 3.解构也可以用于嵌套结构的对象,但要注意谁是模式,谁是被赋值的.
          let obj = {};
          let arr = [];
          ({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });
          obj // {prop:123}
          arr // [true]
      复制代码
    • 4.对象的解构也可以指定默认值,默认值生效的条件是对象的属性值严格等于undefined
      • 如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。结构必须相同.
        •   let {foo: {bar}} = {baz: 'baz'};    //报错
          复制代码
    • 5.圆括号的使用
      • JavaScript 引擎会将{x}理解成一个代码块,必须加圆括号包起来
              let x;
              {x} = {x: 1};//错误
              ({x} = {x: 1});//正确
      复制代码
    • 6.数组本质是特殊的对象,因此可以对数组进行对象属性的解构
          let arr = [1, 2, 3];
          let {0 : first, [arr.length - 1] : last} = arr;
          first // 1
          last // 3
      复制代码
  • 字符串
    • 1.字符串解构赋值,被转换成了一个类似数组的对象
          const [a, b, c, d, e] = 'hello';
          a // "h"
          b // "e"
          c // "l"
          d // "l"
          e // "o"
      复制代码
    • 2.类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。 let {length : len} = 'hello'; len // 5
  • 数值和布尔值
    • 解构赋值时,如果等号右边是数值和布尔值,则会先转为对象
    •   let {toString: s} = 123;
        s === Number.prototype.toString // true
      
        let {toString: s} = true;
        s === Boolean.prototype.toString // true 
      复制代码
    • 解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。
    • 由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
  • 函数参数
    • 参数是数组

    •   [[1, 2], [3, 4]].map(([a, b]) => a + b);
        // [ 3, 7 ]
      复制代码
    • 参数是对象

    •   function move({x = 0, y = 0} = {}) {
            return [x, y];
        }
        move({x: 3, y: 8}); // [3, 8]
        move({x: 3}); // [3, 0]
        move({}); // [0, 0]
        move(); // [0, 0] 
      复制代码
    • 为函数move的参数指定默认值,而不是为变量x和y指定默认值,如果解构失败,x和y等于默认值

    •   function move({x, y} = { x: 0, y: 0 }) {
            return [x, y];
        }
        move({x: 3, y: 8}); // [3, 8]
        move({x: 3}); // [3, undefined]
        move({}); // [undefined, undefined]
        move(); // [0, 0]
      复制代码
    • undefined就会触发函数参数的默认值。

      [1, undefined, 3].map((x = 'yes') => x);
      // [ 1, 'yes', 3 ]
      复制代码

解构赋值的用途

  • 交换变量的值
  • 从函数返回多个值
  • 在函数参数中将一组参数与变量名对应起来
  • 提取 JSON 数据
  • 直接写函数参数的默认值,而不需要逻辑或||表达式
  • 遍历 Map 结构,结合for of循环遍历
  •   const map = new Map();
      map.set('first', 'hello');
      map.set('second', 'world');
      for (let [key, value] of map) {
      console.log(key + " is " + value);
      }
      // first is hello
      // second is world
    
      // 获取键名
      for (let [key] of map) {
      // ...
      }
      // 获取键值
      for (let [,value] of map) {
      // ...
      }
    复制代码
  • 输入模块的指定方法 {模块1,模块2}

字符串的扩展

  • 字符的 Unicode 表示法 \u0061 (忽略)
  • codePointAt(index) 返回字符串索引对应的码点(十进制)
  • codePointAt(index).toString(16) 转为十六进制数
  • String.fromCodePoint() 从码点返回对应字符
  • 字符串的遍历器接口 for ... of
  • at() 识别 Unicode 编号大于0xFFFF的字符,返回正确的字符
  • normalize() 将字符的不同表示方法统一为同样的形式 NFC NFD NFKC NFKD

重要

  • ES5 indexof 确定一个字符串是否包含在另一个字符串
  • includes(字符串参数,搜索位置):返回布尔值,表示是否找到了参数字符串。
  • startsWith(字符串参数,搜索位置):返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith(字符串参数):返回布尔值,表示参数字符串是否在原字符串的尾部。
    • 搜索位置(index索引)从哪里开始,不写,就是默认全部字符串.
    • endsWith(字符串参数,搜索位置),它的搜索位置表示前面的字符串.
  • repeat() 返回一个新字符串,表示将原字符串重复n次。
  • padStart(),padEnd() 字符串补全长度
    • padStart()用于头部补全,padEnd()用于尾部补全
    • 第一个参数是数量,第二个是用于补全的字符
    • 数量小于字符串长度,则返回原字符串
    • 第二个参数不写,则补全的是空格
  • matchAll() 返回一个正则表达式在当前字符串的所有匹配
  • 模板字符串
    • 反引号 ``
    • 如果在模板字符串中需要使用反引号,则前面要用反斜杠转义符`
    • 模板字符串中嵌入变量,需要将变量名写在${}之中
    • 模板编译 嵌套模板引擎
    • 标签模板 ``表示成() 还可以多语言转换
    • String.raw() 返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串

数值的扩展

  • Number.isFinite()用来检查一个数值是否为有限的(finite),即不是Infinity。

  • Number.isNaN()用来检查一个值是否为NaN。

  • Number.parseInt() 取整数

  • Number.parseInt() 取到小数

  • Number.isInteger()用来判断一个数值是否为整数。

  • Number.EPSILON 1 与大于 1 的最小浮点数之间的差

  • 安全整数和 Number.isSafeInteger()

    • 安全整数范围:-2^53到2^53,用Number.MIN_SAFE_INTEGER和Number.MAX_SAFE_INTEGER表示
  • Math的扩展忽略

  • 指数运算符

    • 指数运算符(**)表示相乘
      • 基数**个数
    • 赋值运算符(**=)表示计算结果后再赋值
      • 变量 = 基数
      • 变量 **= 个数
      • 最后变量 = 基数基数基数 (个数)

函数的扩展

1.函数的参数指定默认值

*   指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数
*   length属性也不再计入默认值的参数后面的参数
```
        (function (a, b, c = 5) {}).length // 2
        (function(...args) {}).length // 0
        (function (a, b = 1, c) {}).length // 1
```
*   设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域
    等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的。
        var x = 1;
        function foo(x = x) {
        // ...
        }
        foo() // 报错,暂时性死区
*   利用参数默认值,可以指定某一个参数不得省略,如果省略就抛出一个错误
复制代码
  • 2.rest 参数(形式为...变量名)
    • 获取函数的多余参数,多余的参数放入数组中
  • 3.严格模式 'use strict';
    • 理解: 函数执行的时候,先执行函数参数,然后再执行函数体。不符合严格模式 只有从函数体之中,才能知道参数是否应该以严格模式执行.
    • 规定: 只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错
    •   // 报错
        function doSomething(a, b = a) {
            'use strict';
            // code
        }
        // 报错
        const doSomething = function ({a, b}) {
            'use strict';
            // code
        };
      复制代码
    • 解决办法: 两种方法可以规避这种限制。
      • 第一种是设定全局性的严格模式,这是合法的.
      • 第二种是把函数包在一个无参数的立即执行函数里面。
  • 4.函数的name属性,返回该函数的函数名

5.箭头函数 (=>){}

*   函数体内的this对象,就是定义的对象,而不是调用的对象
*   不可以当作构造函数new命令
*   不可以使用arguments对象,不存在.
*   不可以使用yield命令,不能用作 Generator 函数
*   可以嵌套
复制代码

6.双冒号运算符

*   替代函数上下文调用对象call,apply,bind
*   写法:  对象名::函数名
           对象名::对象名.方法   简写为   :: 对象名.方法        
    都表示这个函数被这个对象调用
*   如果双冒号运算符的运算结果,还是一个对象,就可以采用链式写法 
复制代码
  • 7.函数尾调用
  •   function f(x) {
          if (x > 0) {
              return m(x)
          }
      return n(x);
      }
      //m  n  都属于尾调用
    复制代码
  • 8.函数尾递归
    • 阶乘函数factorial
    • 尾递归函数tailFactorial
    • 函数式编程有一个概念,叫做柯里化(currying) 多参函数转为单参
    • 蹦床函数(trampoline)可以将递归执行转为循环执行
  • 函数参数的尾逗号,

数组的扩展

1.扩展运算符 ... 将一个数组转为用逗号分隔的参数序列

*   console.log(1, ...[2, 3, 4], 5)
     // 1 2 3 4 5
*   扩展运算符后面还可以放置表达式
    const arr = [
        ...(x > 0 ? ['a'] : []),
        'b',
    ];
*   如果扩展运算符后面是一个空数组,则不产生任何效果
    [...[], 1]      // [1]
*   替代函数的 apply 方法 
        // ES5 的写法
        Math.max.apply(null, [14, 3, 77])
        // ES6 的写法
        Math.max(...[14, 3, 77])

        // ES5的 写法
        var arr1 = [0, 1, 2];
        var arr2 = [3, 4, 5];
        Array.prototype.push.apply(arr1, arr2);
        // ES6 的写法
        let arr1 = [0, 1, 2];
        let arr2 = [3, 4, 5];
        arr1.push(...arr2);
复制代码

应用: 复制数组 合并数组 与解构赋值结合

  •   ...字符串转为真正的数组,针对四字节编码
    复制代码
  •   实现了 Iterator 接口的对象 ,把伪数组对象转为了真数组
              let nodeList = document.querySelectorAll('div');
              let array = [...nodeList];
    复制代码
  •   Map 和 Set 结构,Generator 函数
              let map = new Map([
                  [1, 'one'],
                  [2, 'two'],
                  [3, 'three'],
              ]);
              let arr = [...map.keys()]; // [1, 2, 3]
    
              const go = function*(){
                  yield 1;
                  yield 2;
                  yield 3;
              };
              [...go()] // [1, 2, 3]
    复制代码

2.Array.from方法用于将两类对象转为真正的数组:

  • 类似数组的对象和可遍历(iterable)的对象(包括 Set 和 Map)
  • 函数内部的arguments对象
  • DOM 操作返回的集合(querySelectorAll)

3.Array.of方法用于将一组值,转换为数组。

4.数组实例的 copyWithin(三个参数)

target(必需):从该位置开始替换数据。如果为负值,表示倒数。
start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。
end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
复制代码

5.数组实例的 find() 和 findIndex()

  • find() 用于找出第一个符合条件的数组成员
    • 参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。
    • 如果没有符合条件的成员,则返回undefined
    • 回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组
  • findIndex() 返回第一个符合条件的数组成员的位置
    • 如果所有成员都不符合条件,则返回-1
  • 这两个方法都可以接受第二个参数,用来绑定回调函数的this对象。
  •   function f(v){
      return v > this.age;
      }
      let person = {name: 'John', age: 20};
      [10, 12, 26, 15].find(f, person);    // 26
    复制代码
  • 弥补了数组的indexOf方法的不足
  •   [NaN].indexOf(NaN)
      // -1
      [NaN].findIndex(y => Object.is(NaN, y))
      // 0
    复制代码

6.数组实例的 fill()

  • fill方法使用给定值,填充一个数组,会把以前的元素全部替换为给定值
  • fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置

7.数组实例的 entries(),keys() 和 values() 遍历数组

  • 结合for of 循环遍历,keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历
  •   for (let index of ['a', 'b'].keys()) {
          console.log(index);
      }
      // 0
      // 1
    
      for (let elem of ['a', 'b'].values()) {
          console.log(elem);
      }
      // 'a'
      // 'b'
    
      for (let [index, elem] of ['a', 'b'].entries()) {
          console.log(index, elem);
      }
      // 0 "a"
      // 1 "b"
    复制代码
  • 手动调用遍历器对象的next方法,进行遍历
  •   let letter = ['a', 'b', 'c'];
      let entries = letter.entries();
      console.log(entries.next().value); // [0, 'a']
      console.log(entries.next().value); // [1, 'b']
      console.log(entries.next().value); // [2, 'c']
    复制代码

8.数组实例的 includes()

  • 数组是否包含给定的值

9.数组的空位

  • 数组的某一个位置没有任何值.
    • 空位不是undefined,一个位置的值等于undefined,依然是有值的 in运算符,数组的第0个索引对应的元素是否有值

      0 in [undefined, undefined, undefined] // true
      0 in [, , ,] // false
      复制代码
  • ES5
    • forEach(), filter(), reduce(), every() 和some()都会跳过空位。
    • map()会跳过空位,但会保留这个值
    • join()和toString()会将空位视为undefined,而undefined和null会被处理成空字符串。
  • ES6
    • 明确将空位转为undefined
    • Array.from() , 扩展运算符(...), copyWithin()会连空位一起拷贝,fill()会将空位视为正常的数组位置
    • for...of循环也会遍历空位
    • entries()、keys()、values()、find()和findIndex()会将空位处理成undefined。
    •   let arr = [, ,];
            for (let i of arr) {
            console.log(1);
        }
        // 1
        // 1                                                        --------------为什么是两个不是三个???
      复制代码

对象的扩展

  • 属性的赋值器(setter)和取值器(getter)
  • 属性的简洁表示法
  •   const foo = 'bar';
      const baz = {foo};
      baz // {foo: "bar"}
    
      // 等同于
      const baz = {foo: foo};
    复制代码
  • 属性名表达式
  •   obj.foo = true;
    
      obj['abc'] = 123;
    复制代码
  • 属性名表达式与简洁表示法,不能同时使用,会报错
  • 属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object]
  • 对象方法的 name 属性 返回函数名

1.Object.is()

  • 用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致
  •   Object.is('foo', 'foo')
      // true
      Object.is({}, {})
      // false                                                                ----------为什么是错的???对应的地址不一样
    复制代码
  • 不同之处只有两个:一是+0不等于-0,二是NaN等于自身
  •   +0 === -0 //true
      NaN === NaN // false
    
      Object.is(+0, -0) // false
      Object.is(NaN, NaN) // true
    复制代码

2.Object.assign() -----------没写完

  • 对象的合并,第一个参数是目标对象,后面的参数都是源对象
    • 注意:同名属性会发生覆盖
    • 如果该参数不是对象,则会先转成对象,undefined和null无法转成对象,报错
    • 如果是非首参数,即使无法转为对象,只会跳过不会报错.
    • 数值和布尔值都会被忽略
    • 只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)
    • Symbol 值的属性,也会被Object.assign拷贝
注意点:
(1)浅拷贝
(2)同名属性的替换
(3)数组的处理 可以用来处理数组,但是会把数组视为对象
(4)取值函数的处理 只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制。
用处:
(1)为对象添加属性
(2)为对象添加方法
(3)克隆对象
(4)合并多个对象
(5)为属性指定默认值
        所有属性的值,最好都是简单类型,不要指向另一个对象
        同名属性,则会覆盖
复制代码

3.属性的可枚举性和遍历

  • 可枚举性

    • 对象的每个属性都有一个描述对象(Descriptor): Object.getOwnPropertyDescriptor(对象,"属性")
    • 可枚举性:描述对象的enumerable属性.
      • 如果该属性为false,就表示某些操作会忽略当前属性。
      •   for...in循环:只遍历对象自身的和继承的可枚举的属性。
          Object.keys():返回对象自身的所有可枚举的属性的键名。
          JSON.stringify():只串行化对象自身的可枚举的属性。
          Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
        复制代码
    • 所有 Class 的原型的方法都是不可枚举的
  • 遍历

    * (1)for...in
    for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。
    * (2)Object.keys(obj)
    Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
    * (3)Object.getOwnPropertyNames(obj)
    Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
    * (4)Object.getOwnPropertySymbols(obj)
    Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。
    * (5)Reflect.ownKeys(obj)
    Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
复制代码

4.Object.getOwnPropertyDescriptors

*   Object.getOwnPropertyDescriptors方法,返回指定对象所有自身属性(非继承属性)的描述对象。
    *   为了解决Object.assign()无法正确拷贝get属性和set属性的问题。
    *   Object.assign方法总是拷贝一个属性的值,而不会拷贝它背后的赋值方法或取值方法。
*   Object.getOwnPropertyDescriptors方法的另一个用处,是配合Object.create方法,将对象属性克隆到一个新对象。这属于浅拷贝。
复制代码

5.__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()

*   __proto__属性,只有浏览器部署
*   Object.setPrototypeOf()用来设置一个对象的prototype对象,返回参数对象本身
*   Object.getPrototypeOf()用于读取一个对象的原型对象
复制代码

6.super 关键字

*   指向当前对象的原型对象.
*   只能用在对象的方法之中,用在其他地方都会报错。
    *   只有对象方法的简写法可以让 JavaScript 引擎确认,定义的是对象的方法
复制代码

7.Object.keys(),Object.values(),Object.entries()

*   Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。
*   Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
*   Object.entries方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
复制代码

8.对象的扩展运算符... 和解构赋值

*   取出参数对象的所有可遍历属性,拷贝到当前对象之中。
        let z = { a: 3, b: 4 };
        let n = { ...z };    
*   可以用于合并两个对象,注意同名属性会被覆盖
*   与数组的扩展运算符一样,对象的扩展运算符后面可以跟表达式
        const obj = {
            ...(x > 1 ? {a: 1} : {}),
            b: 2,
        };
*   扩展运算符后面是一个空对象,则没有任何效果;参数是null或undefined,这两个值会被忽略,不会报错.
*   扩展运算符的参数对象之中,如果有取值函数get,这个函数是会执行的
复制代码

------------------------下面的是简写--------------------------------

Symbol

  • 保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突
  • Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
  • 只有Object.getOwnPropertySymbols方法,可以遍历获取指定对象的所有 Symbol 属性名
Symbol()
        // 没有参数的情况
        let s1 = Symbol();
        let s2 = Symbol();
        s1 === s2 // false

        // 有参数的情况
        let s1 = Symbol('foo');
        let s2 = Symbol('foo');
        s1 === s2 // false
Symbol.for(),Symbol.keyFor()
    *   Symbol.for(),为了重新使用同一个 Symbol 值
        *   如果有,就返回这个 Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。
                let s1 = Symbol.for('foo');
                let s2 = Symbol.for('foo');
                s1 === s2 // true
    *   Symbol.keyFor(),返回一个已登记的 Symbol 类型值的key,没有就是undefined
复制代码

Set 和 Map 数据结构

  • 1.Set
    • ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
    • Set 本身是一个构造函数,用来生成 Set 数据结构 new Set()
    •   function quchong(array) {
            return Array.from(new Set(array));
        }
        quchong([1, 1, 2, 3]) // [1, 2, 3]
      复制代码
  • Set 实例的属性和方法
    *   Set 结构的实例有以下属性。
        *   Set.prototype.constructor:构造函数,默认就是Set函数。
        *   Set.prototype.size:返回Set实例的成员总数。
    *   Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
        *   add(value):添加某个值,返回 Set 结构本身。
        *   delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
        *   has(value):返回一个布尔值,表示该值是否为Set的成员。
        *   clear():清除所有成员,没有返回值。
    *   Set 结构的实例有四个遍历方法,可以用于遍历成员。
        *   keys():返回键名的遍历器
        *   values():返回键值的遍历器
        *   entries():返回键值对的遍历器
        *   forEach():使用回调函数遍历每个成员
        *   
                let set = new Set(['red', 'green', 'blue']);
                for (let item of set.keys()) {
                    console.log(item);
                }
                // red
                // green
                // blue
复制代码
  • 2.WeakSet
    • WeakSet 的成员只能是对象
    • 垃圾回收机制会自动回收该对象所占用的内存
    • 不可遍历;没有清除方法clear()
  • 3.Map
    *   Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键
    *   Map 也是一个构造函数 new Map()
    *   Map 结构的实例有以下属性和操作方法
            size属性返回 Map 结构的成员总数
            set方法设置键名key对应的键值为value,然后返回整个 Map 结构,可以采用链式写法
            get方法读取key对应的键值,如果找不到key,返回undefined。
            has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
            delete方法删除某个键,返回true。如果删除失败,返回false。
            clear方法清除所有成员,没有返回值。
    *   Map 结构原生提供三个遍历器生成函数和一个遍历方法。Map 的遍历顺序就是插入顺序
            keys():返回键名的遍历器。
            values():返回键值的遍历器。
            entries():返回所有成员的遍历器。
            forEach():遍历 Map 的所有成员。
    *   与其他数据结构的互相转换
        *   Map 转为数组 
                Map 转为数组最方便的方法,就是使用扩展运算符...
        *   数组 转为 Map
        *   Map 转为对象
        *   对象转为 Map
        *   Map 转为 JSON
        *   JSON 转为 Map
复制代码
  • 4.WeakMap
    • 首先,WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。
    • 其次,WeakMap的键名所指向的对象,不计入垃圾回收机制。
    • 没有遍历操作;不支持clear方法

Proxy

  • 在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截.可以对外界的访问进行过滤和改写.
    • var proxy = new Proxy(target, handler);
    • new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。
  • 问题:在 Proxy 代理的情况下,目标对象内部的this关键字会指向 Proxy 代理。

Reflect

  • 将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上.
  •   Reflect.apply(obj, thisArg, args) 改变this指向
      Reflect.construct(obj, args) 调用构造函数
      Reflect.get(obj, name, receiver) 查找obj对象的name属性,函数的this绑定receiver
      Reflect.set(obj, name, value, receiver) 设置obj对象的name属性等于value
      Reflect.defineProperty(obj, name, desc)  为对象定义属性
      Reflect.deleteProperty(obj, name) 删除
      Reflect.has(obj, name) 判断
      Reflect.ownKeys(obj)   返回对象的所有属性
      Reflect.isExtensible(obj) 判断当前对象是否可扩展
      Reflect.preventExtensions(obj) 判断是否操作成功让对象变为不可扩展
      Reflect.getOwnPropertyDescriptor(obj, name)  用于得到指定属性的描述对象
      Reflect.getPrototypeOf(obj) 读取对象原型
      Reflect.setPrototypeOf(obj, prototype) 设置对象原型
    复制代码

Promise 对象

  • 异步编程解决方案
    • 将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数(回调地狱)
    • 写法
    •   const promise = new Promise(function(resolve, reject) {
                if (/* 异步操作成功 */){
                    resolve(value);//成功
                } else {
                    reject(error);//失败
                }
            });
      复制代码
    • Promise.prototype.then() 为 Promise 实例添加状态改变时的回调函数
    • Promise.prototype.catch() 用于指定发生错误时的回调函数
    • Promise.prototype.finally() 不管 Promise 对象最后状态如何,都会执行的操作

Iterator 和 for...of 循环

Iterator

  • “集合”的数据结构:数组(Array)和对象(Object),ES6 又添加了Map和Set
  • 遍历器(Iterator)它是一种接口,为各种不同的数据结构提供统一的访问机制
    • 任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
  • Iterator 的作用有三个:
  •   一是为各种数据结构,提供一个统一的、简便的访问接口;
      二是使得数据结构的成员能够按某种次序排列;
      三是 ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。
    复制代码
  • Iterator 的遍历过程。
  •   (1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
      (2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
      (3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
      (4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。
    复制代码
    • 每一次调用next方法,就是返回一个包含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束
  • ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性.
  •   const obj = {
          [Symbol.iterator] : function () {
              return {
              next: function () {
                  return {
                  value: 1,
                  done: true
                  };
              }
              };
          }
      };
    复制代码
  • 原生具备 Iterator 接口的数据结构如下。
  •   Array
      Map
      Set
      String
      TypedArray
      函数的 arguments 对象
      NodeList 对象
    复制代码

for...of 循环

  • for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、后文的 Generator 对象,以及字符串。
  • 原有的for...in循环,只能获得对象的键名,不能直接获取键值。ES6 提供for...of循环,允许遍历获得键值

Generator 函数的语法

  • 异步编程解决方案

  • Generator 函数是一个状态机,封装了多个内部状态

  • 执行 Generator 函数会返回一个遍历器对象,返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

  • 写法 Generator 函数,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield:产出)。

    function* helloWorldGenerator() {
    yield 'hello';
    yield 'world';
    return 'ending';
    }
    var hw = helloWorldGenerator();
    复制代码
  • Generator 函数可以不用yield表达式,这时就变成了一个单纯的暂缓执行函数

  • yield表达式是暂停执行的标记,返回后面的那个表达式,而next方法可以恢复执行

  • yield表达式即 yield* 函数名(),用来在一个 Generator 函数里面执行另一个 Generator 函数*

  • yield return throw next

Generator 函数的异步应用

  • "协程"(coroutine),意思是多个线程互相协作,完成异步任务
  • Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)

async 异步函数

  • 理解:Generator 函数的语法糖
  • async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已
  • 优点:返回值是 Promise对象

Class 的基本语法(类构造函数)

  • constructor方法,这就是构造方法,而this关键字则代表实例对象
  • 类必须使用new调用,否则会报错。
  • 不存在变量提升;私有方法 _方法名 和私有属性 #属性名

Class 的继承

  • super
  • 子类必须在constructor方法中调用super方法,表示父类的构造函数,用来新建父类的this对象

修饰器(Decorator)函数,用来修改类的行为

  • @函数名 就是一个修饰器

ES6的Module(模块)

  • 模块系统 Ruby 的require、Python 的import,甚至就连 CSS 都有@import
  • ES6之前模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器
  • ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。
  • ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
  • ES6 的模块自动采用严格模式

Module 的加载实现

在浏览器加载 ES6 模块

*   传统方法:浏览器通过<script>标签加载 JavaScript 脚本
        <!-- 页面内嵌的脚本 -->
        <script type="application/javascript">
        // module code
        </script>
        <!-- 外部脚本 -->
        <script type="application/javascript" src="path/to/myModule.js">
        </script>
*   新方法:
        <script src="path/to/myModule.js" defer></script>
        <script src="path/to/myModule.js" async></script>
    *   defer是“渲染完再执行”,有序,async是“下载完就执行”,无序。
        <script type="module" src="./foo.js"></script>
        <!-- 等同于 -->
        <script type="module" src="./foo.js" defer></script>
复制代码

在Node加载 ES6 模块

*   ES6 模块与 CommonJS 模块的差异
        CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
        CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
*   Node 对 ES6 模块的处理比较麻烦,因为它有自己的 CommonJS 模块格式,与 ES6 模块格式是不兼容的。
    目前的解决方案是,将两者分开,ES6 模块和 CommonJS 采用各自的加载方案。
    Node 要求 ES6 模块采用.mjs后缀文件名。
*   注意的问题:
    *   this关键字。ES6 模块之中,顶层的this指向undefined;CommonJS 模块的顶层this指向当前模块。
    *   其次,以下这些顶层变量在 ES6 模块之中都是不存在的。
            arguments   require module   exports __filename  __dirname
*   ES6 模块加载 CommonJS 模块
*   CommonJS 模块加载 ES6 模块
*   循环加载
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值