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
- Common function
Function read() {console.log(' Joshua')} const read = function () { Console. log(' Joshua')}Copy the code
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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 - Return: Arrow functions that have only one expression are implicitly returned without the return keyword
- 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