This is the fifth day of my participation in the August Wen Challenge.More challenges in August

Hello, I’m Joshua (public account). Enthusiastic to do open source, write articles. Objective To help college students, just entering the workplace partners can build their own front-end learning system as soon as possible. If you are confused about your study, please follow me and find me to communicate. I will reply you in real time.

Introduction to ordinary functions and arrow functions

In general, we want to define a function, and there are many ways.

At present, it can be roughly divided into two categories, one is to define a function through the function keyword, called ordinary function and the other is to use the ES6 arrow function syntax, called arrow function

  1. Common function
Function read() {console.log(' Joshua')} const read = function () { Console. log(' Joshua')}Copy the code
  1. Arrow function
Const read = () => {console.log(' Joshua')}Copy the code

So, we should be thinking, what’s the difference between a normal function and an arrow function?

The difference between normal functions and arrow functions

This points to the

Common function

In normal functions, the reference to this (also known as the execution-time context) is dynamic.

The dynamic execution-time context means that the this reference depends on how ordinary functions are called, and there are four ways to call ordinary functions

Let’s take a look

  1. A simple call to a normal function is made directly. This refers to the global object Window, which in strict mode is undefined
function read () {
    console.log(this)
}

read() // window
Copy the code
  1. A normal function is a method property on an object to which this refers
const myObject = { method() { console.log(this); }}; // The function points to myObject.method(); // myObjectCopy the code
  1. Use bind/apply to change what this points to, which points to the first argument of call/apply
function myFunction() {
  console.log(this);
}

const myContext = { value: 'A' };

myFunction.call(myContext);  // logs { value: 'A' }
myFunction.apply(myContext); // logs { value: 'A' }
Copy the code
  1. The new keyword calls a normal function (as a constructor), and this points to the constructed object instance
function MyFunction() { console.log(this); } new MyFunction(); // MyFunction is an instance of an object constructed by the functionCopy the code

Arrow function

In arrow functions, there is no execution context of its own.

The arrow function’s this is defined when the function is defined and bound to the outer function

No matter where or how the arrow function is executed, this always refers to the this of the enclosing function, okay

To be more precise, the arrow function’s this refers to the surrounding function that is closest to its normal function

const myObject = { myMethod(items) { console.log(this); // logs myObject const callback = () => { console.log(this); // logs myObject }; items.forEach(callback); }}; myObject.myMethod([1, 2, 3]);Copy the code

This in callback() is equal to this in myMethod().

The arrow function this, the lexical parsing, is one of the great features of the arrow function.

When we use arrow functions, remember that the arrow function does not have its own this; its this is the this of the nearest normal function outside

So, we can avoid writing:

Const self = this or callback.bind(this)Copy the code

On call/apply, as opposed to normal functions, calling the arrow function indirectly with myarRowfunc.call (thisVal) or myarrowfunc.apply (thisVal) does not change the value of this: the context value is always lexically resolved.

However, if the arrow function is defined globally, this points to the window

var read = () => {
    console.log(this)
}

var obj = {
    read: read
}

obj.read() // window
Copy the code

The constructor

Common function

It is easy to construct an instance of an object using ordinary functions

function Car(color) {
  this.color = color;
}

const redCar = new Car('red');
redCar instanceof Car; // => true
Copy the code

Car is an ordinary function, and when called with the new keyword, an object instance of Car is created

Arrow function

Because of the lexical parsing of this, the arrow function cannot be used as a constructor.

If you try to call an arrow function prefixed with the new keyword, JavaScript throws an error:

const Car = (color) => {
  this.color = color;
};

const redCar = new Car('red'); // TypeError: Car is not a constructor 
Copy the code

Call new Car(‘red’), where Car is an arrow function that raises TypeError: Car is not a constructor.

The arguments object

Common function

In ordinary functions, the keyword arguments are array-like objects that are passed as arguments to a series of functions

function myFunction() { console.log(arguments); } myFunction('a', 'b'); // logs { 0: 'a', 1: 'b', length: 2 }Copy the code

Inside myFunction(), the argument is an array-like object containing the call arguments: ‘a’ and ‘b’.

Arrow function

Arrow function, is no arguments keyword.

As with this, the arguments keyword is lexically resolved: the arrow function calls arguments from an external function. That is, this/arguments always refers to this/arguments of the enclosing function

function outer() {
  const inner = () => {    
      console.log(arguments);  
    }
  inner('c', 'd');
}

outer('a', 'b'); // logs { 0: 'a', 1: 'b', length: 2 }
Copy the code

We can see that the arrow function inner is executed with arguments – ‘c’, ‘d’. While the arrow function inner prints inside, it prints the arguments of the outer function outer

What if the arrow function wants to retrieve arguemts as easily as the normal function does?

Good idea. We could use… The operator

function myRegularFunction() { const myArrowFunction = (... args) => { console.log(args); } myArrowFunction('c', 'd'); } myRegularFunction('a', 'b'); // logs ['c', 'd']Copy the code

When executing the arrow function… [‘c’, ‘d’] – [‘c’, ‘d’]

Invisible return

Common function

In normal functions, XXX is returned if there is a return XXX or if there is no return, undefined

function myFunction() {
  return 42;
}

function myEmptyFunction() {
  42;
}

function myEmptyFunction2() {
  42;
  return;
}

myFunction(); // => 42
myEmptyFunction();  // => undefined
myEmptyFunction2(); // => undefined
Copy the code

Arrow function

In the arrow function, we can do the same thing as normal functions, but there is a neat way to use it. We can return the desired value without using the return keyword

If the arrow function contains only an expression, and you omit the curly braces of the function, the expression will be returned implicitly. These are inline arrow functions.

const increment = (num) => num + 1; increment(41); / / = > 42Copy the code

The increment() arrow contains only one expression: num + 1. This expression is returned implicitly by the arrow function without the return keyword.

Method properties in class

This executes the problem in class

  1. Ordinary functions use ordinary functions as method properties:
class Hero {
  constructor(heroName) {
    this.heroName = heroName;
  }

  logName() {    console.log(this.heroName);  }}

const batman = new Hero('Batman');
Copy the code

Sometimes I need to use the batman.logName callback, such as the event callback or setTimeout() callback, and that’s a little bit of a problem

setTimeout(batman.logName, 1000);
// after 1 second logs "undefined"
Copy the code

Is there a solution? Yes, you can change this by calling/apply

setTimeout(batman.logName.bind(batman), 1000);
// after 1 second logs "Batman"
Copy the code

However, if there is a lot of code, there will be a lot of boilerplate code, which is not very readable

Better yet, use arrow functions in class

2. Arrow function

class Hero {
  constructor(heroName) {
    this.heroName = heroName;
  }

  logName = () => {    console.log(this.heroName);  }}

const batman = new Hero('Batman');

setTimeout(batman.logName, 1000);
// after 1 second logs "Batman"
Copy the code

Methods defined using arrows now refer this lexically to class instances in contrast to normal functions.

Of course, you’re probably wondering, like me, how does the arrow function’s this bind to the class instance? Let’s compile with Babel:

"use strict";

function _defineProperty(obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj[key] = value;
  }
  return obj;
}

class Hero {
  constructor(heroName) {
    _defineProperty(this, "logName", () => {
      console.log(this.heroName);
    });

    this.heroName = heroName;
  }
}

const batman = new Hero("Batman");
Copy the code

Essentially, the class’s this and logName functions are bound via Object.defineProperty. Normal functions, however, do not bind this to a normal object.

conclusion

  1. This refers to: in normal functions, is dynamic and depends on the function call; In the arrow function, the reference to this is fixed because of the syntax, and this is bound to the outer function, or window if there is no outer function
  2. Arguments: In normal functions, all arguments can be retrieved; In arrow functions, arguments refer to arguments for the outer function. If you want to get arguments to the uniformly get arrow function, you can use the...The operator
  3. Return: Arrow functions that have only one expression are implicitly returned without the return keyword
  4. We can use the arrow function in the class, and this will bind to the class instance

That’s the difference between normal functions and arrow functions, hopefully useful ❤❤❤

Under the dynamic hands

  • Follow me on GitHub @huangyangquang ⭐⭐
  • Welcome to follow my official account: Joshua, the front end upperclassman