I am small and live in Wuhan, do two years of new media, ready to use 6 months time to switch to the front end of the industry.

Lesson Objective for today

Yesterday we learned Function data structure based on search. Today is mainly based on search to learn function arrow functions, another day for learning, come on, small and !!!!


Basic instructions

ES6 allows functions to be defined using arrows (=>). Arrow function expressions have a much cleaner syntax than function expressions and don’t have their own this, arguments, super, or new.target. These function expressions are more suitable for places where anonymous functions are needed, and they cannot be used as constructors.



grammar

Basic grammar

(param1, param2,... , paramN) => { statements }/ / is equivalent to
/ / function (param1, param2,... , paramN){ return {statements}; }

(param1, param2,... , paramN) => expression/ / is equivalent to / / function (param1, param2,... , paramN){ return expression; }  // Parentheses are optional when there's only one parameter name: // Parentheses are optional when there is only one argument (singleParam) => { statements } singleParam => { statements }  / / is equivalent to // function(singleParam){ return expression; }  // The parameter list for a function with no parameters should be written with a pair of parentheses. // Functions with no arguments should be written in parentheses. () => { statements } Copy the code

Advanced grammar

// Parenthesize the body of function to return an object literal expression:
// The bracketed function body returns an object literal expression:
params => ({foo: bar})

// Rest parameters and default parameters are supported
// Support remaining parameters and default parameters (param1, param2, ... rest) => { statements }(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements }  // Destructuring within the parameter list is also supported Argument list deconstruction is also supported const f = ([a, b] = [1.2], {x: c} = {x: a + b}) = > a + b + c; f(); / / 6 ` ` `  Copy the code

If the arrow function has more than one statement in its code block, enclose them in braces and return them with a return statement.

const sum = (num1, num2) = > { return num1 + num2; }
Copy the code

This paragraph appears a number of new terms, residual parameters and default parameters, deconstruction, feel some do not understand ~~~~


Arrow function variable scope

Variables defined within the arrow function and their scope

General internal variable

    //
    const greeting_1 = (a)= > {let now = new Date(a);return ("Good" + ((now.getHours() > 17)?" evening." : " day.")); }    console.log(greeting_1());          //"Good evening."
    console.log(now);    // ReferenceError: Now is not defined in the let scope of the standard
Copy the code

parameter

Variables defined in parentheses are local variables (default parameters)

    const greeting_2 = (now=new Date()) = > "Good" + (now.getHours() > 17 ? " evening." : " day.");
    console.log(greeting_2());          //"Good evening."
    console.log(now);    // ReferenceError: now is not defined
Copy the code

The body of a function defines variables

Variables defined by {} inside functions that do not use var are global variables

    const greeting_3 = (a)= > {now = new Date(a);return ("Good" + ((now.getHours() > 17)?" evening." : " day.")); }    console.log(greeting_3());           //"Good evening."
    console.log(now);     // Wed Apr 24 2019 23:02:07 GMT+0800

Copy the code

Variables defined with const in the body of a function {} are local variables

    const greeting_4 = (a)= > {const now = new Date(a);return ("Good" + ((now.getHours() > 17)?" evening." : " day.")); }    console.log(greeting_4()); //"Good evening."
    console.log(now);    // ReferenceError: now is not defined

Copy the code

Main problem solving

Visual optimization

The no-argument arrow function is visually easy to analyze

    setTimeout( (a)= > {
      console.log('I happen sooner');
      setTimeout( (a)= > {
        // deeper code
        console.log('I happen later');
 }, 1);  }, 1); Copy the code

Shorter function

    const elements = [
      'Hydrogen'.      'Helium'.      'Lithium'.      'Beryllium'
 ];   console.log(elements.map(function(element) {  return element.length;  })); // [8, 6, 7, 9]   // The normal function above can be rewritten as the arrow function below  console.log(elements.map((element) = > {  return element.length;  })); // [8, 6, 7, 9]   // If the arrow function has only one argument, omit the parentheses for the argument  console.log(elements.map(element= > {  return element.length;  })); // [8, 6, 7, 9]   // When the body of an arrow function has only one 'return' statement, you can omit the 'return' keyword and the curly braces of the method body  console.log(elements.map(element= > element.length)); // [8, 6, 7, 9]   // In this case, since we only need the 'length' attribute, we can use parameter deconstruction  // Note that string 'length' is the name of the attribute we want to obtain, while 'lengthFooBArX' is just a variable name,  // Can be replaced with any valid variable name  console.log(elements.map(({ "length": lengthFooBArX }) = > lengthFooBArX)); // [8, 6, 7, 9] Copy the code

This is not binding

Before the arrow function, each newly defined function has its own this value (a new object in the case of a constructor, undefined in a strictly modal function call, the underlying object if the function is called as an object method, etc.). This turns out to be a boring object-oriented style of programming.

    function Person() {
      // The Person() constructor defines' this' as its own instance.
      this.age = 0;

      setInterval(function growUp() {
 // In non-strict mode, growUp() defines' this' as a global object,  // Not the same as' this' defined in the Person() constructor.  this.age++;  }, 1000);  }   const p = new Person();  console.log(p);// Person {age: 0} Copy the code

In ECMAScript 3/5, this can be solved by assigning the value to a closed variable.

    function Person() {
      const that = this;
      that.age = 0;

      setInterval(function growUp() {
 // The callback refers to the 'that' variable, whose value is the expected object.  that.age++;  }, 1000);  }  Copy the code

Alternatively, you can create a binding function that passes the pre-allocated this value to the binding's target function (the growUp() function in the above example).

The arrow function does not create its own this; it only inherits this from the upper level of its scope chain. Therefore, in the following code, the value of this in the function passed to setInterval is the same as that in the enclosing function:

    function Person(){
      this.age = 0;

      setInterval((a)= > {
        this.age++; / / | this | to p instance correctly
 }, 1000);  }   const p = new Person(); Copy the code

Do not bind the arguments

Arrow functions do not bind Arguments objects. Thus, arguments in this example simply refers to arguments in a closed scope:

    const arguments = [1.2.3];
    const arr = (a)= > arguments[0];

    console.log(arr()); / / 1

 function foo(n) {  const f = (a)= > arguments[0] + n; Arguments [0] is n  return f();  }   console.log(foo(1)); / / 2 Copy the code

In most cases, using residual arguments is a better choice than using arguments objects.

    function foo(arg) {
      const f = (. args) = > args[0];
      return f(arg);
    }
    console.log(foo(1)); / / 1
  function foo(arg1,arg2) {  const f = (. args) = > args[1];  return f(arg1,arg2);  }  console.log(foo(1.2)); / / 2 Copy the code

Matters needing attention

Methods the function

Arrow function expressions are most appropriate for non-method functions. What happens when you try to use them as methods.

    'use strict';
    const obj = {
      i: 10.      b: (a)= > console.log(this.i, this),
      c: function() {
 console.log(this.i,this)  }  }  console.log(obj.b());  // undefined Window {ƒ : ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, }  // undefined  console.log(obj.c());  // 10 {I: ƒ, b: ƒ, c: ƒ}  // undefined Copy the code

The arrow function does not define the this binding.


Object.defineProperty()

Examples involving Object.defineProperty()

    'use strict';
    const obj = {
      a: 10
    };

 Object.defineProperty(obj, "b", {  get: (a)= > {  console.log(this.a, typeof this.a, this);  return this.a+10; // NaN  // represents the global object 'Window', so 'this.a' returns 'undefined'  }  });   console.log(obj.b); ƒ : ƒ, focus: ƒ, close: ƒ, frames: Window,... } Copy the code

New operator

Arrow functions cannot be used as constructors; using them with new throws an error.

    const Foo = (a)= > {};
    const foo = new Foo(); // TypeError: Foo is not a constructor
Copy the code

The prototype property

Arrow functions have no prototype attribute.

    const Foo = (a)= > {};
    console.log(Foo.prototype); // undefined
Copy the code

yield

The yield keyword usually cannot be used in arrow functions (unless nested within an allowed function). Therefore, arrow functions cannot be used as generators.


The return value is an object literal

Remember that the simple syntax of params => {object:literal} for returning object literals does not work.

Because curly braces are interpreted as blocks of code, if an arrow function returns an object directly, it must enclose parentheses around the object literal or an error will be reported.

    / / an error
    // let getTempItem = id => { id: id, name: "Temp" };

    // No error is reported but no specified return value is obtained
    let getTempItem_1 = id= > { id: id };
  // Returns the specified value without an error  let getTempItem_2 = id= > ({ id: id, name: "Temp" });   console.log(getTempItem_1(123));// undefined  console.log(getTempItem_2(12));// {id: 12, name: "Temp"} Copy the code

In the above code getTempItem_1, the original intent was to return an object {id: id}, but because the engine thought braces were code blocks, it executed a statement id: id.

In this case, id can be interpreted as the label of the statement, so the actual statement executed is ID; , then the function ends with no return value.


Omit braces

If the arrow function has only one line and does not return a value, use the following notation instead of curly braces.

    let fn = (a)= > void doesNotReturn();
Copy the code

A newline

Arrow functions cannot break lines between arguments and arrows.

  const func = (a)
= > 1;
  // SyntaxError: expected expression, got '=>'
Copy the code

Parse order

Although the arrows in arrow functions are not operators, arrow functions have special [Operator Precedence] [operator-precedence] parsing rules that are different from regular functions.

    let callback;

    callback = callback || function() {}; // ok

    callback = callback || (a)= > {};
 // SyntaxError: invalid arrow-function arguments   callback = callback || (() = > {}); // ok Copy the code

The body of the function

Arrow functions can have a shorthand or common block.

In a shorthand, only one expression is required, with an implicit return value attached. In a block, an explicit return statement must be used.

  var func = x= > x * x;
  // The shorthand function omits return

  var func = (x, y) = > { return x + y; };
  // Generally write explicit return values
Copy the code

Relationship to strict patterns

Since this is lexical, rules related to this are ignored in strict mode.

    function Person() {
      this.age = 0;
      const closure = "123"
      setInterval(function growUp() {
        this.age++;
 console.log(closure);  }, 1000);  }   const p = new Person();   function PersonX() {  'use strict'  this.age = 0;  const closure = "123"  setInterval((a)= >{  this.age++;  console.log(closure);  }, 1000);  }   const px = new PersonX();  console.log(px);// PersonX {age: 0} Copy the code

The other rules of strict mode remain the same.


call & apply

Since arrow functions do not have their own this pointer, when a function is called through call() or apply(), only arguments (not this) are passed, and their first argument is ignored. (The same is true for bind.)

    const adder = {
      base : 1.      add : function(a) {
        const f = v= > v + this.base;
        return f(a);
 },   addThruCall: function(a) {  const f = v= > v + this.base;  const b = {  base : 2  };  return f.call(b, a);  }  };   console.log(adder.add(1)); 2 / / output  console.log(adder.addThruCall(1)); // Still outputs 2 (instead of 3) Copy the code

Use case

Simple basic function

The arrow function makes the presentation more concise.

  const isEven = n= > n % 2= = =0;
  const square = n= > n * n;
Copy the code

The above code defines two simple utility functions in just two lines. If you didn't use the arrow function, it would take up multiple lines, and it wouldn't be as bold as it is now.


Concise callback function

One use of the arrow function is to simplify the callback function.

  // The normal function
  [1.2.3].map(function (x) {
    return x * x;
  });

 // arrow function  [1.2.3].map(x= > x * x); Copy the code

Here's another example

  // The normal function
  const result = values.sort(function (a, b) {
    return a - b;
  });

 // arrow function  const result = values.sort((a, b) = > a - b); Copy the code

Array related

Convenient arrays reduce,filter, and Map;

    // Easy array filtering, mapping, ...

    const arr = [5.6.13.0.1.18.23];

    const sum = arr.reduce((a, b) = > a + b);  
 console.log(sum); / / 66   const even = arr.filter(v= > v % 2= =0);  console.log(even); / / [18] 6, 0,   const double = arr.map(v= > v * 2);  console.log(double); // [10, 12, 26, 0, 2, 36, 46] Copy the code

IIFE


    // Empty arrow function returns undefined
    const empty = (a)= > {};

    console.log((() = > 'foobar') ());// foobar
 // (this is an immediate function expression, see the 'IIFE' glossary)  Copy the code

Ternary operator

Arrow functions can also use conditional (ternary) operators

    const simple = a= > a > 15 ? 15 : a;
    console.log(simple(16)); / / 15
    console.log(simple(10)); / / 10

    let max = (a, b) = > a > b ? a : b;
 console.log(max(4.5));/ / 5  Copy the code

Refer to the website

  • arrow function: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
  • Church_encoding: https://en.wikipedia.org/wiki/Church_encoding
  • combinators: https://en.wikipedia.org/wiki/Fixed-point_combinator#Strict_fixed_point_combinator
  • how-to-use-arrow: https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20%26%20beyond/fig1.png
  • Operator-Precedence: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence

Summary of today's lesson



Today the mood

Today is mainly based on the search to learn the basic function arrow function, feel the arrow function is used, the main content is much simpler, and then understand the remaining parameters, default parameters and deconstruction, after a more detailed understanding, I hope to learn more tomorrow ~~~~


This article is formatted using MDNICE