1. 箭头函数和普通函数的区别

    (1)箭头函数比普通函数更简洁:

    • 如果只有一个参数,不用写括号只用写参数
    • 如果只有返回值一句,不用写大括号只用写函数体
    • 可以使用 void 语句来避免返回
      1. let fn1 = a => { return a + 1 }
      2. let fn2 = (a, b) => a + b
      3. let fn3 = () => void doesNotReturn()
      (2)箭头函数没有自己的 this:只会在自己作用域的上一层继承 this,所以箭头函数的 this 的指向在定义时已经确定了
      (3)箭头函数继承来的 this 指向永远不会改变:箭头函数中的 this 永远指向它所定义时所处的全局执行环境的 this
      (4)call、apply、bind 等方法不能改变箭头函数中的 this 的指向:this 不可变动
      (5)箭头函数不能作为构造函数使用:没有自己的 this,也没有 prototype
      (6)箭头函数没有自己的 arguments:不能访问 arguments 类数组对象
      (7)箭头函数没有 prototype
      (8)箭头函数不能用作 Generator,不能使用 yield 关键字
    区别 箭头函数 普通函数
    this 指向 指向静态上下文 可以修改
    构造函数 ✖ ✔
    call、apply、bind 不能改 this,但可以绑定 可以改 this 和绑定
    构造函数 ✖ ✔
    arguments ✖ ✔
    prototype ✖ ✔
    Generator 函数关键字 ✖ ✔
    1. 箭头函数的 this 指向哪里?

    箭头函数并没有自己的 this,因此它所谓的 this 捕获其声明时的上下文,即这个 this 指向箭头函数定义的位置,即箭头函数外层的静态作用域。也因此箭头函数不会被 new 调用,这个 this 也不可能被更改

    1. const obj = {
    2. getArrow() {
    3. return () => {
    4. console.log(this === obj)
    5. }
    6. }
    7. }
    8. // babel 转化后
    9. var obj = {
    10. getArrow: function getArrow() {
    11. var _this = this
    12. return function () {
    13. console.log(_this === obj)
    14. }
    15. }
    16. }
    1. 扩展运算符的作用及使用场景

    (1)对象扩展
    对象的扩展运算符用于取出对象中所有可遍历属性,拷贝到外层的对象之中

    1. let bar = { a:1, b:2 }
    2. let baz = { ...bar }
    3. // 等价于
    4. let bar = { a:1, b:2 }
    5. let baz = Object.assign({}, bar) // { a:1, b:2 }

    如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性
    Object.assign(target, source),assign 会把 source 源对象的所有可枚举属性,复制到 target 目标对象上, target 目标对象最终会被返回
    扩展运算符对对象的拷贝属于浅拷贝

    (2)数组扩展
    数组的扩展运算符可以将一个数组转为逗号分隔的参数序列,且每次只能展开一层数组

    1. [...[1, 2, 3]] /// [1, 2, 3]
    2. [...[1, [2, 3, 4], 5]] /// [1, [2, 3, 4], 5]

    应用:

    • 将数组转换为参数序列

      1. function add(x, y) {
      2. return x + y
      3. }
      4. const numbers = [1, 2]
      5. add(...numbers)
    • 复制数组

      1. const arr1 = [1, 2]
      2. const arr2 = [...arr1]
    • 合并数组

      1. const arr1 = ['two', 'three']
      2. const arr2 = ['one', ...arr1, 'four', 'five']
    • 扩展运算符合结构运算符结合,用于生成数组,注意扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错

      1. const [ first, ...rest ] = [1,2,3,4,5]
      2. first // 1
      3. rest // [2, 3, 4, 5]
    • 将字符串转为真正的数组,类似 split

      1. [...'hello'] // ['h','e','l','l','o']
    • 任何 iterator 接口的对象,都可以用扩展运算符转为真正的数组

      1. // 转化类数组等其他数据结构,到数组
      2. // 可以用于替换 es5 的 Array.prototype.slice.call(arguments) 写法
      3. function foo() {
      4. const args = [...arguments]
      5. }