JavaScript pointer functions may look the same on the surface as regular functions, but they have some very important differences:
- Syntax differences
this
Value (execution context)- Used as a method
- As a constructor
arguments
bundled
grammar
The first and most obvious difference between pointer functions and regular functions is their syntax. Not only do they look different, but the arrow functions also provide implicit return abbreviations and allow the parentheses around individual arguments to be omitted.
const square = a => a * a;
// Equivalent regular function
function square(a) {
return a * a;
}
Copy the code
Execution context
In regular functions, the execution context (that is, the value of this) is dynamically relative. This means that the value of this depends on how the function is called (simple call, method call, indirect call, or constructor call). Arrow functions, on the other hand, do not define their own execution context. This results in this lexical parsing of the arrow function (that is, defining the scope of the arrow function).
function logThis() {
console.log(this);
}
document.addEventListener('click', logThis);
// `this` refers to the document
const logThisArrow = () => {
console.log(this);
};
document.addEventListener('click', logThisArrow);
// `this` refers to the global object
Copy the code
Function.prototype.call(), function.prototype.bind () and function.prototype.apply () don’t work properly with arrow functions either. Their purpose is to allow methods to execute in different scopes, but this cannot change the value of the arrow function because it is lexical.
function logThis() {
console.log(this);
}
logThis.call(42); // Logs: 42
const logThisArrow = () => {
console.log(this);
};
logThisArrow.call(42); // Logs the global object
Copy the code
A method is called
Because pointer functions do not define their own execution context, they are less suitable for direct method calls. However, due to Class Fields Proposal, pointer functions can be used as methods in a Class if your environment supports them.
const obj = {
x: 42,
logThisX: function() {
console.log(this.x, this);
},
logThisXArrow: () => {
console.log(this.x, this);
}
};
obj.logThisX(); // Logs: 42, Object {...}
obj.logThisXArrow(); // Logs: undefined, the global object
Copy the code
The constructor
You can use the new keyword to use regular functions as constructors. Another consequence of lexical parsing of the this internal pointer functions is that they cannot be used as constructors. Using new in an arrow effect results in TypeError.
function Foo(bar) {
this.bar = bar;
}
const a = new Foo(42); // Foo {bar: 42}
const Bar = foo => {
this.foo = foo;
};
const b = new Bar(42); // TypeError: Bar is not a constructor
Copy the code
parameter
Another difference is the binding of arguments objects. Unlike regular functions, pointer functions don’t have their own arguments objects. A modern alternative to this limitation is to use the remaining parameters.
function sum() { return arguments[0] + arguments[1]; }; sum(4, 6); // 10 const arguments = [1, 2, 3]; const sumArrow = () => { return arguments[0] + arguments[1]; }; sumArrow(4, 6); // 3 (resolves to 1 + 2) const sumRest = (... arguments) => { return arguments[0] + arguments[1]; } sumRest(4, 6); / / 10Copy the code
Other differences
Finally, there are some other differences that are less important but worth mentioning. These include the missing properties in the Prototype pointer function and the fact that the yield keyword may not be used in the body of the arrow function. The latter result is that pointer functions cannot be used as generators.