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
- The arrow function this points to the first normal function in the outer layer of the definition, regardless of the position used.
- 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 itsargumens
Inherits 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:
-
Arrow functions and normal functions can be used.
-
More flexible, the number of parameters received is fully customized.
-
Better readability
Arguments are defined in parentheses. Arguments do not suddenly appear.
-
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:
-
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
-
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.
usenew
Calling 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.
-
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
-
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!
-
Arrow functions are anonymous and do not write function
-
We can omit the parentheses when we have only one argument:
var f = a= > a; // Pass a to return a Copy the code
-
{} 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
-
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
-
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
- Arrow functions cannot wrap lines between arguments and arrows!
var func = (a)= > 1; // error: Unexpected token =>
Copy the code
- 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.
- 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!
- 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.
-
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:
- Arrow function doesn’t have any
prototype
(prototype), so the arrow function itself does not have this - The arrow function’s this is defined as inheriting from the outer layer’s this.
- If the arrow function has no normal function surrounding it, its this points to in both strict and non-strict modes
window
(Global object) - The arrow function’s own this pointer cannot be changed, but can modify the this of the object it inherits from.
- The arrow function this points to global; using arguments raises an undeclared error.
- The arrow function this points to a normal function when its
argumens
Inherits from the ordinary function - use
new
Calling the arrow function returns an error because the arrow function does not have oneconstructor
- Arrow functions are not supported
new.target
- Arrow functions do not support renaming function arguments. Function arguments of normal functions support renaming
- Arrow functions have a more concise and elegant syntax than normal functions
Precautions of arrow function and not applicable scenarios
Note for arrow functions:
- Arrow function a statement that returns an object literal, parenthesized
- Arrow functions cannot break lines between arguments and arrows
- 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?