Arrow functions are a new syntax added in ES6
that provide a more concise way of writing functions, similar to anonymous functions, and simplify function definition.
The full syntax is similar to an anonymous function, omitting the function
keyword.
var s = (a,b) => {
console.log(a, b); // 1 2
return a + b;
}
s(1,2);
// Equivalent to
var s = function(a,b) {
console.log(a, b); // 1 2
return a + b;
}
s(1,2);
When there is only one parameter, parentheses can be omitted. It is not possible to omit parentheses when there are no parameters or when there are more than two parameters.
var s = a => {
console.log(a); // 1
return a + a;
}
s(1);
// Equivalent to
var s = function(a) {
console.log(a); // 1
return a + a;
}
s(1);
When the function body has only one line of code, {}
can be omitted, and the value of this line will be automatically returned.
var cmp = (a, b) => a - b;
var a = [5, 4, 3, 2, 1];
var sortedArr = a.sort(cmp);
console.log(sortedArr); // [1, 2, 3, 4, 5]
// Equivalent to
var cmp = function(a, b) { return a - b; };
var a = [5, 4, 3, 2, 1];
var sortedArr = a.sort(cmp);
console.log(sortedArr); // [1, 2, 3, 4, 5]
When both of the above conditions are met, parentheses and braces can be omitted altogether.
var s = a => a * 2;
console.log(s(1)); // 2
// Equivalent to
var s = function(a) { return a * 2; }
console.log(s(1)); // 2
When returning an object, it is important to wrap it in ()
; otherwise, the {}
of the object will be interpreted as the beginning and ending of the arrow function's body by the browser.
var s = a => ({"a": a * 2});
console.log(s(1)); // {a: 2}
// Equivalent to
var s = function(a) { return {"a": a * 2}; }
console.log(s(1)); // {a: 2}
Arrow functions do not have a separate this
. When this
is used in the function body of an arrow function, it will access the this
of its surrounding context. Arrow functions do not create their own this
when called; it only inherits this
from the level of its scope chain. Since arrow functions do not have their own this
pointer, using apply
, call
, or bind
can only pass arguments but cannot dynamically change the this
pointer of the arrow function.
var obj = {
s1: () => {
console.log(this);
},
s2: function(){
console.log(this);
}
}
obj.s1(); // Window ...
obj.s2(); // {s1: ƒ, s2: ƒ}
/*
When called, the running environment is the Window, and as s1 is an arrow function, it does not change its `this` pointer, so it points to the Window.
s2 is a regular function and can change its `this` pointer, so it points to the caller.
*/
var contextObj = {
e: function() {
var obj = {
s1: () => {
console.log(this);
},
s2: function(){
console.log(this);
}
}
obj.s1(); // {e: ƒ}
obj.s2(); // {s1: ƒ, s2: ƒ}
}
}
contextObj.e();
/*
When called, the running environment is the contextObj object, and as s1 is an arrow function, it does not change its `this` pointer, so it points to the contextObj object.
s2 is a regular function and can change its `this` pointer, so it points to the caller.
*/
Utilizing the this
pointing feature of arrow functions can solve some problems, such as the common issue of this
pointing in callback functions.
// Common issue of the `this` pointing in callback functions
var a = 1;
var obj = {
a: 2,
run: function(){
var callback = function(){
console.log(this.a);
}
setTimeout(callback,1000); // 1 // The `this` of the callback points to the Window
}
}
obj.run();
To solve this issue, the this
value can be assigned to an enclosed variable.
var a = 1;
var obj = {
a: 2,
run: function(){
var that = this;
var callback = function(){
console.log(that.a);
}
setTimeout(callback,1000); // 2
}
}
obj.run();
Alternatively, bind
can be used to bind the this
during function execution.
var a = 1;
var obj = {
a: 2,
run: function(){
var callback = function(){
console.log(this.a);
}
setTimeout(callback.bind(this),1000); // 2
}
}
obj.run();
By using arrow functions, you can directly write callback functions without changing the this
reference. Arrow functions do not create their own this
; instead, they inherit the this
from their lexical enclosing scope.
var a = 1;
var obj = {
a: 2,
run: function(){
var callback = () => {
console.log(this.a);
}
setTimeout(callback,1000); // 2
}
}
obj.run();
Arrow functions do not bind the arguments
object. When referencing arguments
within an arrow function, it refers to the arguments
of the enclosing scope, and does not create its own 'this' and 'arguments' within its own scope.
function s(a,b){
console.log(...arguments); // 1 2
var ss1 = (c) => {
console.log(...arguments); // 1 2
}
var ss2 = function(c){
console.log(...arguments); // 3
}
ss1(3);
ss2(3);
}
s(1, 2);
Arrow functions cannot be used as constructors and will throw an exception when instantiating with new
.
var s = () => {};
new s(); // Uncaught TypeError: s is not a constructor
Arrow functions do not have a prototype
property.
var s = () => {};
console.log(s.prototype); // undefined
Arrow functions cannot be used as generators. The yield
keyword typically cannot be used inside arrow functions, unless it is nested within a function that allows it.
https://github.com/WindrunnerMax/EveryDay
https://segmentfault.com/a/1190000010159725
https://www.runoob.com/w3cnote/es6-function.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions