ES6: Arrow function

Keywords: Lambda ECMAScript REST Javascript

lambda functions are anonymous functions. Before ES6 was released, we usually wrote anonymous functions like this.

var selected = allJobs.filter(function (job) {
      return job.isSelected();
    });

ES6 introduces a new grammar for writing functions

var selected = allJobs.filter(job => job.isSelected());

Its syntax is very simple: identifier=> expression. To write a function that accepts multiple parameters (or may not have parameters, or indefinite parameters, default parameters, parameter deconstruction), you need to wrap the parameter list in parentheses.

    // ES5
    var total = values.reduce(function (a, b) {
      return a + b;
    }, 0);
    // ES6
    var total = values.reduce((a, b) => a + b, 0);

In addition to expressions, arrow functions can also contain a block statement.

    // ES5
    $("#confetti-btn").click(function (event) {
      playTrumpet();
      fireConfettiCannon();
    });
    // ES6
    $("#confetti-btn").click(event => {
      playTrumpet();
      fireConfettiCannon();
    });

Note that arrow functions that use block statements do not automatically return values. You need to use return statements to return the required values.
Tip: When using arrow functions to create ordinary objects, you always need to wrap them in parentheses.

// Create a new empty object for each puppies
var chewToys = puppies.map(puppy => {}); // This will report Bug!
var chewToys = puppies.map(puppy => ({})); //Wrap empty objects in parentheses

Unfortunately, an empty object {} looks exactly the same as an empty block {}. The rule in ES6 is that {is parsed as the beginning of the block, not the beginning of the object, following the arrow. Therefore, the code puppy => {} is resolved to have no behavior and returns the undefined arrow function.

Unbound this

Before the arrow function appeared, each newly defined function had its own this value.

function Person() {
  // The constructor Person() defines `this'as the new instance object itself
  this.age = 0;
  setInterval(function growUp() {
    // In the non-strict mode, the growUp() function defines its internal `this'.`
    // Is a global object, different from the constructor Person() definition of `this'.`
    this.age++; 
  }, 1000);
}

var p = new Person();

In ECMAScript 3/5, this problem can be solved by adding a variable to the expected this object, and then putting the variable in the closure.

function Person() {
  var self = this; // Others choose to use `that'instead of `self'. 
                   // Just be consistent.
  self.age = 0;

  setInterval(function growUp() {
    // The `self'variable in the callback points to the desired object.
    self.age++;
  }, 1000);
}

The arrow function captures the value of this in its context as its own value of this, so the following code will run as scheduled.

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| Pointed correctly person object
  }, 1000);
}

var p = new Person();

this value when using call or apply calls?

The first parameter of call() and apply() is the object of the function to be called. In the function body, this parameter is the value of the key word this, and the remaining parameter is the value passed to the function to be called. When an arrow function calls a function through call() or apply(), it just passes in parameters, which has no effect on this:

var adder = {
  base : 1,

  add : function(a) {
    var f = v => v + this.base;
    return f(a);
  },

  addThruCall: function(a) {
    var f = v => v + this.base;
    var b = {
      base : 2
    };

    return f.call(b, a);
  }
};

console.log(adder.add(1));         // Output 2
console.log(adder.addThruCall(1)); // Still output 2 (not 3)

Unbound arguments

The arrow function does not expose arguments objects inside it: arguments.length, arguments[0], arguments[1], etc. It does not point to arguments of the arrow function, but points to a value called arguments (if any, undefined) in the scope of the arrow function.

var arguments = 42;
var arr = () => arguments;

arr(); // 42

function foo() {
  var f = () => arguments[0]; // foo's implicit arguments binding
  return f(2);
}

foo(1); // 1 (not 2)

The arrow function does not have its own arguments object, but in most cases the rest parameter can provide a solution:

function foo() { 
  var f = (...args) => args[0]; 
  return f(2); 
}

foo(1); // 2

Also note that the arrow function can't be used as a constructor and throws an error when used with new. Arrow function can not change lines between parameters and arrows.

Reference link:
http://www.infoq.com/cn/articles/es6-in-depth-arrow-functions
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Posted by dansk on Wed, 10 Jul 2019 12:03:33 -0700