PCDotFan

To be an life & code artisan

ES6 - 箭头函数

JavaScript 0 评

「箭头函数」相较于之前的「匿名函数」其优点是具有更简明的语法、可以隐式返回、不绑定this

更简明的语法 & 隐式返回

    let a = [1,2,3,4,5,6,7,8,9]
    let aPlusOne = a.map(function(x) {
      return x + 1;
    })
    console.log(aPlusOne); // (9) [2, 3, 4, 5, 6, 7, 8, 9, 10]

以上,map 的参数是 function(x) 这一个匿名函数,对数组的每一个元素 +1。有了 ES6,这一段代码可以这样修改:

    let a = [1,2,3,4,5,6,7,8,9]
    let aPlusOne = a.map( x => {
      return x + 1;
    })
    console.log(aPlusOne);

也就是去掉了前面的 function 声明,将迭代器 x 直接写在 a.map 内作为参数。用一个箭头 => 指向函数块。

哦当然咯,如果匿名函数内的参数不止一个,那么之前的 a.map(x => ...) 还是需要将参数用括号包起来,像这样:a.map( (x,y) => ...)

实际上,如果这个「匿名函数」的作用能简单到只用一行 return 就搞定的话,以上代码还能再简单一点:

    let a = [1,2,3,4,5,6,7,8,9]
    let aPlusOne = a.map( x => x+1);
    console.log(aPlusOne);

箭头直接指向 return 后的表达式,这就是 隐式返回

不绑定 this

我并不太懂这个「不绑定 this」更深层次是虾米意思……回头仔细看看,先照搬例子。

    let Computer = {
      company: 'ThinkPad',
      name: 'Carbon X1',
      features: ['fast', 'inexpensive', 'squared-shape'],
      ram: '8G',
      printFeatures: function() {
        this.features.map(function(feature) {
          console.log(`${this.name} is ${feature}`);
        })
      }
    }
    Computer.printFeatures(); // TypeError: Cannot read property 'name' of undefined

这里我们给 Computer 这个对象的 printFeatures 属性声明了一个匿名函数,但奇怪的是似乎取不到 this.name。 常规做法,我们会先给检查 this 是否绑定在 Computer 上:

    let Computer = {
        // ...
        printFeatures: function() {
        this.features.map(function(feature) {
          console.log(this);
         //  console.log(`${this.name} is ${feature}`);
        })
      }
    }
    Computer.printFeatures(); // undefined

实际上,console.log(this)features.map 内的匿名函数里面,既不是直接赋值给对象上的属性,又没用什么 callback 之类的方法——导致 this 实际上指向的是 window 或者是 undefined(严格模式下) 在 ES5,可以使用这样的 Hack:

    // ...
      printFeatures: function() {
        var computer = this;
        this.features.map(function(feature) {
          console.log(`${computer.name} is ${feature}`); // Carbon X1 is fast ...
        })
      }
  // ...

由于 var 是函数作用域,且 this 所指向的也是 Computer 这个变量,则自然代码可以正常运行。 在 ES6 则没有这么麻烦了,直接使用「箭头函数」就可以避免这种不必要的尴尬:

    // ...
    printFeatures: function() {
        this.features.map(feature => {
          console.log(`${this.name} is ${feature}`);
        })
      }
    // ...

为什么呢?实际上,箭头函数根本「没有自己的 this」:

this 对象的指向是可变的,但是在箭头函数中,它是固定的。this 指向的固定化,并不是因为箭头函数内部有绑定 this 的机制,实际原因是箭头函数根本没有自己的 this,导致内部的 this 就是外层代码块的 this。正是因为它没有 this,所以也就不能用作构造函数。

箭头函数雷区

ES6 标准入门 - 阮一峰 箭头函数使用注意点: (1)函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。 (2)不可以当作构造函数,也就是说,不可以使用 new 命令,否则会抛出一个错误。 (3)不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。