ES6+常用语法2

104 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

对象

  1. Object.assign()

    const obj1 = {
      a: 1,
      b: 2,
      c: 3,
    }
    
    const obj2 = {
      b: 4,
      c: 5,
      d: 6,
    }
    
    const obj3 = Object.assign(obj1, obj2)
    
    console.log(obj3) // { a: 1, b: 4, c: 5, d: 6 }
    

    Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

  2. 简洁表示法

    const str = 'hello'
    
    const arr = [1, 2, 3]
    
    const obj = {
      str,
      arr,
      a: 1,
    }
    
    console.log(obj) // { str: 'hello', arr: [1, 2, 3], a: 1 }
    

函数

  1. 箭头函数

    const foo = () => {
      console.log('foo')
    }
    
    foo() // foo
    

    箭头函数表达式的语法比函数表达式更简洁,没有自己的 this,arguments,super 或 new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方。

    箭头函数不能用作构造函数。

  2. 参数默认值

    function foo(x = 1, y = 2) {
      console.log(x, y)
    }
    
    foo() // 1 2
    foo(2) // 2 2
    foo(2, 3) // 2 3
    foo(undefined, 3) // 1 3
    
  3. 参数展开

    function foo(x, y, ...rest) {
      console.log(x, y, rest)
    }
    
    foo(1, 2, 3, 4, 5) // 1 2 [3, 4, 5]
    

    ... 可以放在任何参数的最后一位,用于获取函数调用时所有未被消费的参数。

数据结构

  1. Set

    const set = new Set([1, 2, 3, 4, 5])
    
    console.log(set.has(1)) // true
    console.log(set.has(6)) // false
    console.log(set.size) // 5
    

    Set 数据结构是一个无序的集合,每个元素都唯一。

  2. Map

    const myMap = new Map([['name', 'Tom']])
    console.log(myMap.get('name')) // Tom
    
    myMap.set('age', 25) // 添加键值对
    console.log(myMap.has('age')) // true
    
    myMap.delete('age') // 删除键值对
    console.log(myMap.has('age')) // false
    
    myMap.set(NaN, 'not a number') // Map 的键可以是任意值,包括函数、对象或任意基本类型
    console.log(myMap.get(NaN)) // "not a number"
    
    console.log(myMap.size) // 3
    
    // Map 可以直接被迭代
    myMap.forEach((value, key) => {
      console.log(key + ' = ' + value) // name = Tom NaN = not a number
    })
    

    Map 数据结构是键值对集合,一个 Map 的键可以是任意值,包括函数、对象或任意基本类型。Map 可以直接被迭代。

其它

  1. 扩展运算符(展开语法)

    const arr = [1, 2]
    console.log(...arr) // 1 2
    
    const str = 'hello'
    console.log(...str) // h e l l o
    
  2. for in

    const obj = { a: 1, b: 2 }
    
    for (let key in obj) {
      console.log(key) // a b
    }
    

    for in 可以遍历对象的键名。

  3. for of

    const arr = [1, 2]
    
    for (let item of arr) {
      console.log(item) // 1 2
    }
    

    for of 可以遍历数组的成员。

  4. class

    class Student {
      constructor(name) {
        this.name = name
      }
    
      sayName() {
        console.log(`My name is ${this.name}`)
      }
    }
    
    const student = new Student('Bob')
    
    student.sayName() // My name is Bob
    

    class 关键字用于创建一个类。可以理解为 ES5 的构造函数的语法糖。

  5. Promise

    const asyncFunc = new Promise((resolve, rejcet) => {
      Math.random() > 0.5 ? resolve('fulfilled') : rejcet('rejected')
    })
    
    asyncFunc
      .then(data => {
        console.log(data) // fulfilled
      })
      .catch(err => {
        console.log(err) // rejected
      })
      .finally(() => {
        console.log('finally')
      })
    

    Promise 是 ES6 新增的一种异步操作解决方案。Promise 对象的状态可以有 3 个:pendingfulfilledrejected。当状态发生改变时,会触发相应的回调函数。

  6. async/await

    async function hello() {
      return await Promise.resolve('Hello')
    }
    
    hello().then(console.log) // Hello
    

    async/await 是 ES2017 中新增的异步解决方案。简单来说,它们是基于 Promise 的语法糖,使异步代码更易于编写和阅读。

    async 函数返回一个 Promise 对象,await 关键字只能用在 async 函数中,不能用在其他函数中。

  7. Proxy

    const cat = {
      name: 'Tom',
    }
    
    const myCat = new Proxy(cat, {
      get(target, property) {
        console.log(`我的 ${property} 被读取了`)
        return property in target ? target[property] : undefined
      },
      set(target, property, value) {
        console.log(`我的 ${property} 被设置成了 ${value}`)
        target[property] = value
        return true
      },
    })
    
    myCat.name // expected output: 我被读取了:name
    myCat.name = 'Kitty' // expected output: 我的 name 被设置成了 Kitty
    

    Proxy 可以代理任何对象,包括数组。

    Proxy 可以直接监听整个对象而非属性,比 Object.defineProperty() 更加简洁,更加高效,更加安全。

    Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的。

  8. Reflect

    const cat = {
      name: 'Tom',
    }
    
    Reflect.set(cat, 'age', 5)
    
    console.log(Reflect.get(cat, 'name')) // Tom
    
    console.log(cat.age) // 5
    
    console.log(Reflect.has(cat, 'name')) // true
    
    console.log(Reflect.ownKeys(cat)) // ['name', 'age']
    

    Reflect 是一个对象,而非构造函数。主要用于访问和修改对象的属性。

    ReflectObject 看似雷同,但存在许多差异

  9. Symbol

    const mySymbol = Symbol()
    
    console.log(typeof mySymbol) // "symbol"
    
    console.log(Symbol() === Symbol()) // false
    

    Symbol 是 ES6 新增的一种基本数据类型。Symbol 表示一个独一无二的值。

  10. Generator

    function* helloWorldGenerator() {
      yield 'hello'
      yield 'world'
      return 'ending'
    }
    
    const hw = helloWorldGenerator()
    
    console.log(hw.next()) // { value: 'hello', done: false }
    console.log(hw.next()) // { value: 'world', done: false }
    console.log(hw.next()) // { value: 'ending', done: true }
    

    Generator 是 ES6 新增的一种异步编程模型。

    Generator 函数是一个状态机,遇到 yield 就会暂停执行,并返回一个 { value, done } 的对象,value 属性表示返回的值,done 属性表示是否完成。

  11. Module

    // math.js
    export function add(x, y) {
      return x + y
    }
    
    // app.js
    import { add } from './math'
    
    console.log(add(1, 2)) // 3
    

    Module 是 ES6 新增的模块化语法,可以将代码拆分成多个文件,并且可以通过 importexport 来导入和导出。

使用 Babel 将 ES6+ 转换为 ES5

  • 为什么要将 ES6+ 转换为 ES5?

    因为 ES6+ 是 JavaScript 的新语法,我们虽然可以在开发时使用,但是直接运行在浏览器中的话,许多语法浏览器是不支持的,所以要将 ES6+ 转换为 ES5。

  • 为什么要使用 Babel?

    Babel 是一个 JavaScript 编译器,可以将 ES6+ 转换为 ES5。

  • 安装 Babel

    npm i @babel/core babel-loader @babel/preset-env -D
    

    @babel/core 是 Babel 的核心包。

    babel-loader 是 Webpack 的 loader,用于在 Webpack 打包时调用 Babel,从而将 ES6+ 转换为 ES5。

    @babel/preset-env 提供了一些预置的 Babel 配置,这是一个智能预设,只要安装这一个 preset,就会根据你设置的目标浏览器,自动将代码中的新特性转换成目标浏览器支持的代码。

    -D 表示安装到 package.json 中的开发依赖。

  • 在 Webpack 中使用 Babel

    module.exports = {
      module: {
        rules: [
          {
            test: /.js$/,
            exclude: /node_modules/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env'],
              },
            },
          },
        ],
      },
    }