Arrow function is ES6 API, I believe many people know, because of its syntax compared to ordinary functions more concise, loved by everyone. This is the API we have been using in daily development, but most of the students do not have a deep understanding of it…

The difference between normal and arrow functions:

The arrow function this points to the rule:

1. Arrow function does notprototype(prototype), so the arrow function itself does not have this

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

2. The arrow function this points to this, which inherits from the first normal function in the outer layer when it is defined.

Define the arrow function in one function and then execute the arrow function in the other.

let a,
  barObj = { msg: 'Bar this points to' };
fooObj = { msg: 'Foo's this points to' };
bar.call(barObj); // Point bar's this to barObj
foo.call(fooObj); // Point foo's this to fooObj
function foo() {
  a(); // result: {MSG: 'bar this'}
}
function bar() {
  a = (a)= > {
    console.log(this.'This refers to the first normal function in the outer layer of the definition'); // 
  }; // Define this in bar to inherit the this pointer of the bar function
}
Copy the code

Two points can be drawn from the chestnut above

  1. The arrow function this points to the first normal function in the outer layer of the definition, regardless of the position used.
  2. The this of the inherited normal function changes, and the this of the arrow function changes with it

3. You cannot directly modify the this pointer of the arrow function

To modify the function foo in the previous example, try modifying the arrow function this directly.

let fnObj = { msg: 'Try modifying the arrow function's this pointer directly' };
function foo() {
  a.call(fnObj); // result: {MSG: 'bar this'}
}
Copy the code

Call clearly shows that the bind this pointer failed, including aaply and bind.

They (call, aaply, bind) ignore the first argument by default, but pass it as normal.

Then I tried using implicit binding again and failed. The new call gives an error, but more on that later.

SO, the arrow function cannot directly modify its this pointer.

Fortunately, we can change the direction of the arrow function in an indirect way:

Modify the this pointer of the inherited normal function, and then the this pointer of the arrow function will also change, as demonstrated in the previous chestnut.

bar.call(barObj); // Point bar's normal function this to barObj and then the inner arrow function will also point to barObj
Copy the code

4. There is no normal function outside the arrow function. Its this points to both strict and non-strict modeswindow(Global object)

Well, the question was actually raised by the interviewer. At the time, I thought that the rule of arrow function this was that the arrow function this refers to the this that inherits from the first ordinary function in the outer layer. Now it seems to be really lax (at least one definition). If the definition and execution are not in the same ordinary function, where does it point to?

Since this of the arrow function refers to this, which inherits from the first normal function in the outer layer when defined:

Where does the arrow function this point when there is no ordinary function around it?

This is not the same as the “this” binding rule. The default binding rule for normal functions is:

In non-strict mode, the default binding this refers to a global object, and in strict mode this refers to undefined

If the arrow function has no ordinary function inheritance, its this refers to the rule:

After testing, the arrow function’s this refers to the window(global object) in both strict and non-strict mode.

Strict mode is declared invalid at the beginning of the global/function when tested:

a = 1;
'use strict'; // Strict mode invalid must be declared at the outset
b = 2; / / is not an error
Copy the code

Arrow function

Arguments for the arrow function

The arrow function this points to global; using arguments raises an undeclared error

Error if arrow function this points to window(global object); arguments are not declared.

let b = (a)= > {
  console.log(arguments);
};
b(1.2.3.4); // Uncaught ReferenceError: arguments is not defined
Copy the code

PS: If you declare a global variable as arguments, you will not get an error, but why would you do that?

The arrow function this points to a normal function when itsargumensInherits from the ordinary function

The above is the first case: the arrow function this points to a global object and raises an undeclared error.

The second case is: The arrow function’s this if it points to a normal function, its argumens inherit from that normal function.

function bar() {
  console.log(arguments); // [' outer second normal function argument ']
  bb('Arguments to the first ordinary function in the outer layer');
  function bb() {
    console.log(arguments); // [" outer first normal function argument "]
    let a = (a)= > {
      console.log(arguments.'Arguments inherit from the normal function to which this points'); // [" outer first normal function argument "]
    };
    a('Arguments to arrow function'); // this points to bb
  }
}
bar('Argument to the second ordinary function in the outer layer');
Copy the code

So how do you get an indefinite number of arguments for the arrow function? The answer is: REST parameters for ES6 (… Extended operator)

The rest argument gets the extra arguments of the function

This is ES6 API, used to capture function array variable number of parameters, this API is used to replace the arguments, API usage is as follows:

let a = (first, ... abc) = > {
  console.log(first, abc); // 1 [2, 3, 4]
};
a(1.2.3.4);
Copy the code

The above example shows an example of getting a function divided by the first determined argument and receiving the remaining arguments with a variable.

You can also accept all arguments to a function. Rest arguments can be used as arguments:

  1. Arrow functions and normal functions can be used.

  2. More flexible, the number of parameters received is fully customized.

  3. Better readability

    Arguments are defined in parentheses. Arguments do not suddenly appear.

  4. Rest is a real array, and you can use the API for arrays.

    Since arguments is an array-like object, some people assume it is a real array, so the following scenarios occur:

    arguments.push(0); // arguments.push is not a function
    Copy the code

    As above, if we need to use the Array API, we need to use the extension/array. from to convert it to a real Array:

    arguments= [...arguments]; Or:arguments = Array.from(arguments);
    Copy the code

There are two things to note about the REST parameter:

  1. Rest must be the last argument to the function:

    let a = (first, ... rest, three) = > {
      console.log(first, rest,three); Rest parameter must be last formal parameter
    };
    a(1.2.3.4);
    Copy the code
  2. The length property of the function, excluding the REST argument

    (function(. a) {}).length  / / 0
    (function(a, ... b) {}).length  / / 1
    Copy the code

Extended operators can also be used with arrays. Here is ruan Yifeng’s document

PS: I feel I have written too much here, but I like to make a point of knowledge clear.

usenewCalling the arrow function returns an error

Calling the arrow function from new returns an error regardless of where the arrow function’s thsi points because the arrow function has no constructor

let a = (a)= > {};
let b = new  a(); // a is not a constructor
Copy the code

Arrow functions are not supportednew.target:

New. target is a new attribute introduced in ES6. If a normal function is called from new, new.target returns a reference to that function.

This property determines whether the constructor is called by new.

  1. The arrow function this points to the global object. Using the arrow function inside the arrow function will cause an error

    let a = (a)= > {
      console.log(new.target); // Error: new.target is not allowed here
    };
    a();
    Copy the code
  2. The arrow function’s this points to a normal function, and its new.target is a reference to that normal function.

    new bb();
    function bb() {
      let a = (a)= > {
        console.log(new.target); // point to function bb: function bb(){... }
      };
      a();
    }
    Copy the code

For more information about New. target, please read ruan Yifeng’s explanation about this section.

Arrow functions do not support renaming function arguments. Function arguments of normal functions support renaming

As shown in the following example, a normal function argument can be renamed, the last one overwrites the previous one, and the arrow function throws an error:

function func1(a, a) {
  console.log(a, arguments); / / 2 [1, 2]
}

var func2 = (a,a) = > {
  console.log(a); // Error: duplicate parameter names are not allowed in this context
};
func1(1.2); func2(1.2);
Copy the code

Arrow functions have a more concise and elegant syntax than normal functions:

Speaking reason, the difference on grammar, also belong to the difference with them two!

  1. Arrow functions are anonymous and do not write function

  2. We can omit the parentheses when we have only one argument:

    var f = a= > a; // Pass a to return a
    Copy the code
  3. {} and return can be omitted when a function has only one statement

    var f = (a,b,c) = > a; // pass a,b,c to return a
    Copy the code
  4. Simplify callbacks to make your callbacks more elegant:

[1.2.3].map(function (x) {
  return x * x;
}); // the function can be written as a function
[1.2.3].map(x= > x * x); // The arrow function only needs one line
Copy the code

Precautions of arrow function and not applicable scenarios

Note for arrow functions

  1. One statement returns an object literal, parenthesized, or written as multiple statements.

    Otherwise, as demonstrated in func, curly braces will be parsed into curly braces of multiple statements and will not parse properly

var func1 = (a)= > { foo: 1 }; // To return an object, braces are parsed as multiple statements, and undefined is returned after execution
var func2 = (a)= > ({foo: 1}); // Parentheses are the correct way to write
var func2 = (a)= > {
  return {
    foo: 1 // It is better to write as multiple statements
  };
};
Copy the code
  1. Arrow functions cannot wrap lines between arguments and arrows!
var func = (a)= > 1;  // error: Unexpected token =>
Copy the code
  1. Arrow functions are parsed relatively first

MDN: Although the arrows in arrow functions are not operators, arrow functions have special operator priority resolution rules that are different from regular functions

let a = false || function() {}; // ok
let b = false || (a)= > {}; // Malformed arrow function parameter list
let c = false || (() = > {}); // ok
Copy the code

The arrow function does not apply to the following scenarios:

Around two points: the unexpected orientation of the arrow function this and the readability of the code.

  1. Define the literal method, the unexpected pointer to this.

Because of the simplicity of the arrow function

const obj = {
  array: [1.2.3].sum: (a)= > {
    // There is no ordinary function this that refers to the global object
    return this.array.push('There's no array in the global object, this is an error'); // Can't find push method}}; obj.sum();Copy the code

There is no problem with using a normal function or ES6 method shorthand to define a method:

// These two expressions are equivalent
sum() {
  return this.array.push('this point to obj);
}
sum: function() {
  return this.array.push('this point to obj);
}
Copy the code

Another case is when methods are defined on the prototype of a normal function, usually outside of the normal function, such as when inheriting/adding methods.

Since this is not defined inside a normal function, it points to other normal functions, or to global objects, causing a bug!

  1. Callback function dynamic this

Here is an example of a dom text modification operation that failed because this pointed to an error:

const button = document.getElementById('myButton');
button.addEventListener('click', () = > {this.innerHTML = 'Clicked button'; // This is global again
});
Copy the code

I’m sure you already know, if I change it to a normal function.

  1. Consider the readability of your code and use normal functions

    • Complex function body:

      Specific expression is the arrow function using multiple ternary operation symbols, is not newline, must be written in a line, very disgusting!

    • Number of lines is more

    • There are a lot of operations inside the function

Summary of the article content:

The difference between normal and arrow functions:

  1. Arrow function doesn’t have anyprototype(prototype), so the arrow function itself does not have this
  2. The arrow function’s this is defined as inheriting from the outer layer’s this.
  3. If the arrow function has no normal function surrounding it, its this points to in both strict and non-strict modeswindow(Global object)
  4. The arrow function’s own this pointer cannot be changed, but can modify the this of the object it inherits from.
  5. The arrow function this points to global; using arguments raises an undeclared error.
  6. The arrow function this points to a normal function when itsargumensInherits from the ordinary function
  7. usenewCalling the arrow function returns an error because the arrow function does not have oneconstructor
  8. Arrow functions are not supportednew.target
  9. Arrow functions do not support renaming function arguments. Function arguments of normal functions support renaming
  10. Arrow functions have a more concise and elegant syntax than normal functions

Precautions of arrow function and not applicable scenarios

Note for arrow functions:

  1. Arrow function a statement that returns an object literal, parenthesized
  2. Arrow functions cannot break lines between arguments and arrows
  3. Arrow functions are parsed in opposite order||The front

Not applicable: unexpected this pointing of the arrow function and code readability.


conclusion

It can be said that it is very complete. Anyway, when I was first asked about it, I could only think of the arrow function “This” which is inherited from me and the simplicity of grammar. I don’t know anything else.

PS: Currently looking for a job, ask the big guys to push inside, middle and senior front-end, partial JS, Vue, Shanghai Yangpu.

Blog, front-end accumulation of documents, public account, GitHub, Wx :OBkoro1, email: [email protected]

The above 2019.03.22

References:

MDN arrow function

Ruan Yifeng – Introduction to ES6

When can you not use arrow functions?