javascript - Arrow function vs function declaration / expressions: Are they equivalent / exchangeable? -
canonical question if find question issues after replacing function declaration / expression arrow function, please close duplicate of one.
arrow functions in es2015 provide more concise syntax. can replace function declarations / expressions arrow functions now? have out for?
examples:
constructor function
function user(name) { this.name = name; } // vs const user = name => { this.name = name; }; prototype methods
user.prototype.getname = function() { return this.name; }; // vs user.prototype.getname = () => this.name; object (literal) methods
const obj = { getname: function() { // ... } }; // vs const obj = { getname: () => { // ... } }; callbacks
settimeout(function() { // ... }, 500); // vs settimeout(() => { // ... }, 500); variadic functions
function sum() { let args = [].slice(arguments); // ... } // vs const sum = () => { let args = [].slice(arguments); // ... };
tl;dr: no! arrow functions , function declarations / expressions not equivalent , cannot replaced blindly.
if function want replace not use this, arguments , not called new, yes.
as often: it depends. arrow functions have different behavior function declarations / expressions, lets have @ differences first:
1. lexical this , arguments
arrow functions don't have own this or arguments binding. instead, identifiers resolved in lexical scope other variable. means inside arrow function, this , arguments refer values of this , arguments in environment arrow function defined in (i.e. "outside" arrow function):
// example using function expression function createobject() { console.log('inside `createobject`:', this.foo); return { foo: 42, bar: function() { console.log('inside `bar`:', this.foo); }, }; } createobject.call({foo: 21}).bar(); // override `this` inside createobject // example using arrow function function createobject() { console.log('inside `createobject`:', this.foo); return { foo: 42, bar: () => console.log('inside `bar`:', this.foo), }; } createobject.call({foo: 21}).bar(); // override `this` inside createobject in function expression case, this refers object created inside createobject. in arrow function case, this refers this of createobject itself.
this makes arrow functions useful if need access this of current environment:
// common pattern var = this; getdata(function(data) { that.data = data; }); // better alternative arrow functions getdata(data => { this.data = data; }); note means not possible set arrow function's this .bind or .call.
if not familiar this, consider reading
2. arrow functions cannot called new
es2015 distinguishes between functions callable , functions constructable. if function constructable, can called new, i.e. new user(). if function callable, can called without new (i.e. normal function call).
functions created through function declarations / expressions both constructable , callable.
arrow functions (and methods) callable. class constructors constructable.
if trying call non-callable function or construct non-constructable function, runtime error.
knowing this, can state following.
replaceable:
- functions don't use
thisorarguments. - functions used
.bind(this)
not replaceable:
- constructor functions
- function / methods added prototype (because use
this) - variadic functions (if use
arguments(see below))
lets have closer @ using examples:
constructor function
this won't work because arrow functions cannot called new. keep using function declaration / expression or use class.
prototype methods
most not, because prototype methods use this access instance. if don't use this, can replace it. however, if care concise syntax, use class concise method syntax:
class user { constructor(name) { this.name = name; } getname() { return this.name; } } object methods
similarly methods in object literal. if method wants reference object via this, keep using function expressions, or use new method syntax:
const obj = { getname() { // ... }, }; callbacks
it depends. should replace if you aliasing outer this or using .bind(this):
// old settimeout(function() { // ... }.bind(this), 500); // new settimeout(() => { // ... }, 500); but: if code calls callback explicitly sets this specific value, case event handlers, jquery, , callback uses this (or arguments), cannot use arrow function!
variadic functions
since arrow functions don't have own arguments, cannot replace them arrow function. however, es2015 introduces alternative using arguments: rest parameter.
// old function sum() { let args = [].slice.call(arguments); // ... } // new const sum = (...args) => { // ... }; related question:
- when should use arrow functions in ecmascript 6?
- do es6 arrow functions have own arguments or not?
- what differences (if any) between es6 arrow functions , functions bound function.prototype.bind?
- how use es6 arrow in class methods?
further resources:
Comments
Post a Comment