ES6常用语法和方法总结

ES6阮一峰老师的书已经出到第三版了,从中受益匪浅,第二版读了三遍,在项目中常用到的一些语法和方法做些总结

字符串扩展

常用的一些方法

  1. at()

    // 参数传入角标,返回值为角标对应的字符
    'abc'.at(0) // 'a'
    '吉'.at(0)  // '吉'
    // 与ES5中charAt()不同之处,汉字的话ES5会返回对应Unicode编码,js内部用UTF-16
    
  2. includes(), startsWith(), endsWith()

    • includes(),返回值为布尔值,表示是否找到参数的字符串
    • startsWith(),返回值为布尔值,表示参数字符串是否在原字符串的头部
    • endsWith(),返回布尔值,表示参数字符串是否在原字符串的尾部
    • 这三个方法都支持第二个参数,表示开始搜索的位置。endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。
    let str = 'Hello World'
    str.includes('Hello')   // true
    str.startsWith('Hello') // true
    str.endsWith('d')   // true
    str.startsWith('world', 6) // true
    str.endsWith('Hello', 5) // true
    str.includes('Hello', 6) // false
    
  3. repeat()

    'x'.repeat(3) // "xxx"
    
    • 注意:参数不能传负数和Infinity,参数NaN为0,参数为字符串会先转换为数字
  4. padStart(),padEnd()

    • 参数两个,第一个为位数,第二个是用什么补全,省略第二个参数时默认为空格补全。这两个更多的用途是补全指定位数
    '1'.padStart(10, '0') // "0000000001"
    '12'.padStart(10, '0') // "0000000012"
    '123456'.padStart(10, '0') // "0000123456"
    

数组扩展

  1. Array.from()

    Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)

  2. ...运算符

    扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

    console.log(...[1, 2, 3])
    // 1 2 3
    
    console.log(1, ...[2, 3, 4], 5)
    // 1 2 3 4 5
    
    • 关于函数传参的问题,如果函数直接用...传参,传入的参数实际上是个数组,且后面不能再有参数。如果函数参数定义了一个数组,用...传入,实际上参数为数组中的值
    function fn(...items){}
    //等同于
    function fn([数组内容]){}
    
    let items = ['a', 'b', 'c']
    function fn(...items){}
    // 等同于
    function fn('a', 'b', 'c') {}
    
  3. ...运算符的应用

    • 复制数组(克隆数组)
    let arr1 = [1, 2, 3]
    let arr2 = [...arr1] // [1, 2, 3]
    
    • 合并数组
    const arr1 = ['a', 'b']
    const arr2 = ['c']
    const arr3 = ['d', 'e']
    const arr4 = [...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ]
    
    • 与解构赋值结合
    const [first, ...rest] = [1, 2, 3, 4, 5];
    first // 1
    rest  // [2, 3, 4, 5]
    
    • 将字符串转换为真正的数组
    [...'hello']
    // [ "h", "e", "l", "l", "o" ]
    
  4. Array.of(), 用于将一组值,转换为数组。

    Array.of(3, 11, 8) // [3,11,8]
    Array.of(3) // [3]
    Array.of(3).length // 1
    
  5. 数组实例的fill()

    • 三个参数,后面两个可以省略,第一个参数为替换成什么内容,第二个为替换的起始位置,第三个为替换的终止位置
    ['a', 'b', 'c'].fill(7)
    // [7, 7, 7]
    
    ['a', 'b', 'c'].fill(7, 1, 2)
    // ['a', 7, 'c']
    
  6. 数组实例的 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"
    

对象扩展

对象的话,解构赋值就不说了太基础了,我用的最多的就是...运算符和Object.assgin(),好吧,实际上...底层的方法就是assign()

Symbol

js数据类型除了string,number,boolean,undefined,null,object,第七种为symbol,他的作用就是防止定义变量时出现重复的定义导致覆盖的一些问题,这个我知道有这个,但从没用过

Set和Map结构

  1. Set

    ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,用来生成Set数据结构。此结构不会添加重复的值(你想到了什么,一定想到了数组去重)

    // 例一
    const set = new Set([1, 2, 3, 4, 4]);
    [...set]
    // [1, 2, 3, 4]
    
    // 例二
    const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
    items.size // 5
    
    // 例三 数组去重
    [...new Set(array)]
    
  2. Map

    这个结构我个人感觉不如对象好用,没用过。实际上Map结构就是键值对的结构,里面设置和获取分别用set和get方法,我要设置的话每次都set一下,我觉得很不方便

Proxy拦截

  1. 基本说明

    Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

    var obj = new Proxy({}, {
      get: function (target, key, receiver) {
        console.log(`getting ${key}!`);
        return Reflect.get(target, key, receiver);
      },
      set: function (target, key, value, receiver) {
        console.log(`setting ${key}!`);
        return Reflect.set(target, key, value, receiver);
      }
    });
    
  2. get()方法

    get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(即this关键字指向的那个对象),其中最后一个参数可选。

    var person = {
      name: "张三"
    };
    
    var proxy = new Proxy(person, {
      get: function(target, property) {
        if (property in target) {
          return target[property];
        } else {
          throw new ReferenceError("Property \"" + property + "\" does not exist.");
        }
      }
    });
    
    proxy.name // "张三"
    proxy.age // 抛出一个错误
    
  3. set()方法

    set方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。

    let validator = {
      set: function(obj, prop, value) {
        if (prop === 'age') {
          if (!Number.isInteger(value)) {
            throw new TypeError('The age is not an integer');
          }
          if (value > 200) {
            throw new RangeError('The age seems invalid');
          }
        }
    
        // 对于满足条件的 age 属性以及其他属性,直接保存
        obj[prop] = value;
      }
    };
    
    let person = new Proxy({}, validator);
    
    person.age = 100;
    
    person.age // 100
    person.age = 'young' // 报错
    person.age = 300 // 报错
    

async和await

  1. 基本说明

    async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

  2. await命令

    正常情况下,await命令后面是一个 Promise 对象。如果不是,会被转成一个立即resolve的 Promise 对象。

    async function f() {
      return await 123;
    }
    
    f().then(v => console.log(v))
    // 123
    

class类

说明几个问题

  1. constructor()

    constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。

    class Point {
    }
    
    // 等同于
    class Point {
      constructor() {}
    }
    
  2. 类继承中的super()

    如果你要用类继承的话,里面一定要写super(),他是指定父类的this的,否则会报错

    class A {}
    
    class B extends A {
      constructor() {
        super();
      }
    }
    

浏览器加载

  1. defer和async

    
    
    

    defer与async的区别是:defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。

  2. ES6的新语法

    浏览器加载 ES6 模块,也使用

    • ES6 模块也允许内嵌在网页中,语法行为与加载外部脚本完全一致。
    
    

    对于外部的模块脚本(上例是foo.js),有几点需要注意。

     - 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见。
     - 模块脚本自动采用严格模式,不管有没有声明use strict。
     - 模块之中,可以使用import命令加载其他模块(.js后缀不可省略,需要提供绝对 URL 或相对 URL),也可以使用export命令输出对外接口。
     - 模块之中,顶层的this关键字返回undefined,而不是指向window。也就是说,在模块顶层使用this关键字,是无意义的。
     - 同一个模块如果加载多次,将只执行一次。
    

附:阮老师的开源ES6第三版电子书 http://es6.ruanyifeng.com/

你可能感兴趣的:(ES6常用语法和方法总结)