1

0x000 概述

箭头函数有两个作用:

  1. 更简短的写法
  2. 不绑定this

0x001 语法一表览

()=>{}
()=>{console.log('arrow');return null}
()=>'hello'
(num1, num2)=>num1+num2
num=>++num
()=>({name:'arrow'})

0x002 写法

  1. 正规一点

    let add = (num1, num2)=>{
       return num1 + num2
    }
    add(1, 2)

    声明了一个add变量,该变量是一个加法函数,该函数有两个形参:num1num2,返回值为这两个参数相加的结果

  2. 单参数

    let  increment = num=>{
        return num + 1
    }

    上面声明了一个increment变量,该变量是一个自增函数,该参数只有一个形参num,返回值为该参数自增1,因为只有一个参数,所以可以省略箭头函数参数列表的()

  3. 无参数

    let now = () => {
        return Date.now()
    }
    let now==>{} // Uncaught SyntaxError: Unexpected token ==

    上面声明了一个now变量,该变量是一个函数,可以获取当前时间戳,因为不需要参数,所以参数列表置空,但是这种情况下不能将()省略,否则将导致语法错误

  4. 单一返回值

    let now = () =>  Date.now()

    上面函数还可以简写为以下方式,因为函数体只有一句话,所以可以省略{}return

  5. 单一返回值:返回对象字面量
    虽然箭头函数可以省略{}return,但是在返回一个对象字面量的时候要格外注意,如果是像下面的写法,虽然在语法检查的时候不会报错,但是和你所期望的可能不太一样,比如这里,你希望得到的数据是{name:'hello'},但是结果却是undefined

    let data=()=>{name:'hello'} // 不会报错 
    console.log(data()) // undefined

    为什么呢?用babel解析一下

    clipboard.png

    可以发现,被解析成了

    var data = function data() {
      name: 'hello';
    };

    并没有return,对比4的例子
    clipboard.png
    所以,其实{name:'hello'}被解析成了函数体,{}是函数的{},而不是对象的{},而name:'hello'被解析成了语句,这种语句不常用,却是满足js语法的,叫做标签,案例:

    var str = "";
    
    loop1:
    for (var i = 0; i < 5; i++) {
      if (i === 1) {
        continue loop1;
      }
      str = str + i;
    }
    
    console.log(str); // 0234

    所以如果箭头函数需要返回单一的对象字面量,需要加对()

    let data=()=>({name:'hello'}) 

0x003 不绑定this

看下面一种情况

function Person() {
  this.age = 0;

  setInterval(function growUp() {
    console.log(this.age)
  }, 1000);
}

var p = new Person();

通常,我们希望在setInterval的回调函数中访问Person的变量,比如age,但是每个新定义的函数都有自己的this,所以这里的thisgrowUpthis,并不是Personthis,这将导致this.age将会得到undefined,为了解决这种问题,我们通常会使用折中的解决方案:

function Person() {
  this.age = 0;
  var that=this
  setInterval(function growUp() {
    console.log(that.age)
  }, 1000);
}

var p = new Person();

用一个临时变量that来持有this,避免使用growUpthis,这个时候就轮到箭头函数上场了:

function Person() {
  this.age = 0;
  setInterval(()=> {
    console.log(this.age)
  }, 1000);
}

var p = new Person();

在箭头函数中,是不会绑定this的,也就是他没有自己的this,所以这个时候,他的this,就是Personthis。这就是所谓的箭头函数不绑定this,而在我看来,回调函数就是箭头函数最好的归宿。
babel解析之后的结果其实还是老方法:

"use strict";

function Person() {
  var _this = this;

  this.age = 0;
  setInterval(function () {
    console.log(_this.age);
  }, 1000);
}

var p = new Person();

0x004 注意

  1. 箭头函数支持默认参数

    let add = (num1 = 0, num2) => num1 + num2
  2. 箭头函数支持剩余参数

    let add = (...numList) => numList.reduce((n1, n2) => n1 + n2)
  3. 箭头函数支持参数列表解构

    let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
  4. 箭头函数不支持arguments,如果要使用arguments,推荐上面的剩余参数的写法

    // 栗子1
    var arguments = [1, 2, 3];
    var arr = () => arguments[0];
    
    arr(); // 1
    // 栗子2
    function foo(n) {
      var f = () => arguments[0] + n; // 隐式绑定 foo 函数的 arguments 对象. arguments[0] 是 n
      return f();
    }
    
    foo(1); // 2
    // 栗子3
    function foo() { 
      var f = (...args) => args[0]; 
      return f(2); 
    }
    
    foo(1); 
    // 2
  5. Object.defineProperty()会出现意料之外的影响

    'use strict';
    var obj = {
      a: 10
    };
    
    Object.defineProperty(obj, "b", {
      get: () => {
        console.log(this.a, typeof this.a, this);
        return this.a+10; 
       // 代表全局对象 'Window', 因此 'this.a' 返回 'undefined'
      }
    });
  6. 无法和new一起使用

    var Foo = () => {};
    var foo = new Foo(); // TypeError: Foo is not a constructor
  7. 没有prototype

    var Foo = () => {};
    console.log(Foo.prototype); // undefined
  8. 解析顺序有影响

    let callback;
    
    callback = callback || function() {}; // ok
    
    callback = callback || () => {};      
    // SyntaxError: invalid arrow-function arguments
    
    callback = callback || (() => {});    // ok

0x005 资源


followWinter
1.5k 声望82 粉丝

暂时没有