Proper use of Ecmascript 6 syntax: "=>" or "function(){...} [duplicate] - javascript

With () => {} and function () {} we are getting two very similar ways to write functions in ES6. In other languages lambda functions often distinguish themselves by being anonymous, but in ECMAScript any function can be anonymous. Each of the two types have unique usage domains (namely when this needs to either be bound explicitly or explicitly not be bound). Between those domains there are a vast number of cases where either notation will do.
Arrow functions in ES6 have at least two limitations:
Don't work with new and cannot be used when creating prototype
Fixed this bound to scope at initialisation
These two limitations aside, arrow functions could theoretically replace regular functions almost anywhere. What is the right approach using them in practice? Should arrow functions be used e.g.:
"everywhere they work", i.e. everywhere a function does not have to be agnostic about the this variable and we are not creating an object.
only "everywhere they are needed", i.e. event listeners, timeouts, that need to be bound to a certain scope
with 'short' functions, but not with 'long' functions
only with functions that do not contain another arrow function
I am looking for a guideline to selecting the appropriate function notation in the future version of ECMAScript. The guideline will need to be clear, so that it can be taught to developers in a team, and to be consistent so that it does not require constant refactoring back and forth from one function notation to another.
The question is directed at people who have thought about code style in the context of the upcoming ECMAScript 6 (Harmony) and who have already worked with the language.

A while ago our team migrated all its code (a mid-sized AngularJS app) to JavaScript compiled using Traceur Babel. I'm now using the following rule of thumb for functions in ES6 and beyond:
Use function in the global scope and for Object.prototype properties.
Use class for object constructors.
Use => everywhere else.
Why use arrow functions almost everywhere?
Scope safety: When arrow functions are used consistently, everything is guaranteed to use the same thisObject as the root. If even a single standard function callback is mixed in with a bunch of arrow functions there's a chance the scope will become messed up.
Compactness: Arrow functions are easier to read and write. (This may seem opinionated so I will give a few examples further on.)
Clarity: When almost everything is an arrow function, any regular function immediately sticks out for defining the scope. A developer can always look up the next-higher function statement to see what the thisObject is.
Why always use regular functions on the global scope or module scope?
To indicate a function that should not access the thisObject.
The window object (global scope) is best addressed explicitly.
Many Object.prototype definitions live in the global scope (think String.prototype.truncate, etc.) and those generally have to be of type function anyway. Consistently using function on the global scope helps avoid errors.
Many functions in the global scope are object constructors for old-style class definitions.
Functions can be named1. This has two benefits: (1) It is less awkward to writefunction foo(){} than const foo = () => {} — in particular outside other function calls. (2) The function name shows in stack traces. While it would be tedious to name every internal callback, naming all the public functions is probably a good idea.
Function declarations are hoisted, (meaning they can be accessed before they are declared), which is a useful attribute in a static utility function.
Object constructors
Attempting to instantiate an arrow function throws an exception:
var x = () => {};
new x(); // TypeError: x is not a constructor
One key advantage of functions over arrow functions is therefore that functions double as object constructors:
function Person(name) {
this.name = name;
}
However, the functionally identical2 ECMAScript Harmony draft class definition is almost as compact:
class Person {
constructor(name) {
this.name = name;
}
}
I expect that use of the former notation will eventually be discouraged. The object constructor notation may still be used by some for simple anonymous object factories where objects are programmatically generated, but not for much else.
Where an object constructor is needed one should consider converting the function to a class as shown above. The syntax works with anonymous functions/classes as well.
Readability of arrow functions
The probably best argument for sticking to regular functions - scope safety be damned - would be that arrow functions are less readable than regular functions. If your code is not functional in the first place, then arrow functions may not seem necessary, and when arrow functions are not used consistently they look ugly.
ECMAScript has changed quite a bit since ECMAScript 5.1 gave us the functional Array.forEach, Array.map and all of these functional programming features that have us use functions where for loops would have been used before. Asynchronous JavaScript has taken off quite a bit. ES6 will also ship a Promise object, which means even more anonymous functions. There is no going back for functional programming. In functional JavaScript, arrow functions are preferable over regular functions.
Take for instance this (particularly confusing) piece of code3:
function CommentController(articles) {
this.comments = [];
articles.getList()
.then(articles => Promise.all(articles.map(article => article.comments.getList())))
.then(commentLists => commentLists.reduce((a, b) => a.concat(b)));
.then(comments => {
this.comments = comments;
})
}
The same piece of code with regular functions:
function CommentController(articles) {
this.comments = [];
articles.getList()
.then(function (articles) {
return Promise.all(articles.map(function (article) {
return article.comments.getList();
}));
})
.then(function (commentLists) {
return commentLists.reduce(function (a, b) {
return a.concat(b);
});
})
.then(function (comments) {
this.comments = comments;
}.bind(this));
}
While any one of the arrow functions can be replaced by a standard function, there would be very little to gain from doing so. Which version is more readable? I would say the first one.
I think the question whether to use arrow functions or regular functions will become less relevant over time. Most functions will either become class methods, which make away with the function keyword, or they will become classes. Functions will remain in use for patching classes through the Object.prototype. In the mean time I suggest reserving the function keyword for anything that should really be a class method or a class.
Notes
Named arrow functions have been deferred in the ES6 specification. They might still be added a future version.
According to the draft specification, "Class declarations/expressions create a constructor function/prototype pair exactly as for function declarations" as long as a class does not use the extend keyword. A minor difference is that class declarations are constants, whereas function declarations are not.
Note on blocks in single statement arrow functions: I like to use a block wherever an arrow function is called for the side effect alone (e.g., assignment). That way it is clear that the return value can be discarded.

According to the proposal, arrows aimed "to address and resolve several common pain points of traditional function expressions". They intended to improve matters by binding this lexically and offering terse syntax.
However,
One cannot consistently bind this lexically
Arrow function syntax is delicate and ambiguous
Therefore, arrow functions create opportunities for confusion and errors, and should be excluded from a JavaScript programmer's vocabulary, replaced with function exclusively.
Regarding lexical this
this is problematic:
function Book(settings) {
this.settings = settings;
this.pages = this.createPages();
}
Book.prototype.render = function () {
this.pages.forEach(function (page) {
page.draw(this.settings);
}, this);
};
Arrow functions intend to fix the problem where we need to access a property of this inside a callback. There are already several ways to do that: One could assign this to a variable, use bind, or use the third argument available on the Array aggregate methods. Yet arrows seem to be the simplest workaround, so the method could be refactored like this:
this.pages.forEach(page => page.draw(this.settings));
However, consider if the code used a library like jQuery, whose methods bind this specially. Now, there are two this values to deal with:
Book.prototype.render = function () {
var book = this;
this.$pages.each(function (index) {
var $page = $(this);
book.draw(book.currentPage + index, $page);
});
};
We must use function in order for each to bind this dynamically. We can't use an arrow function here.
Dealing with multiple this values can also be confusing, because it's hard to know which this an author was talking about:
function Reader() {
this.book.on('change', function () {
this.reformat();
});
}
Did the author actually intend to call Book.prototype.reformat? Or did he forget to bind this, and intend to call Reader.prototype.reformat? If we change the handler to an arrow function, we will similarly wonder if the author wanted the dynamic this, yet chose an arrow because it fit on one line:
function Reader() {
this.book.on('change', () => this.reformat());
}
One may pose: "Is it exceptional that arrows could sometimes be the wrong function to use? Perhaps if we only rarely need dynamic this values, then it would still be okay to use arrows most of the time."
But ask yourself this: "Would it be 'worth it' to debug code and find that the result of an error was brought upon by an 'edge case?'" I'd prefer to avoid trouble not just most of the time, but 100% of the time.
There is a better way: Always use function (so this can always be dynamically bound), and always reference this via a variable. Variables are lexical and assume many names. Assigning this to a variable will make your intentions clear:
function Reader() {
var reader = this;
reader.book.on('change', function () {
var book = this;
book.reformat();
reader.reformat();
});
}
Furthermore, always assigning this to a variable (even when there is a single this or no other functions) ensures one's intentions remain clear even after the code is changed.
Also, dynamic this is hardly exceptional. jQuery is used on over 50 million websites (as of this writing in February 2016). Here are other APIs binding this dynamically:
Mocha (~120k downloads yesterday) exposes methods for its tests via this.
Grunt (~63k downloads yesterday) exposes methods for build tasks via this.
Backbone (~22k downloads yesterday) defines methods accessing this.
Event APIs (like the DOM's) refer to an EventTarget with this.
Prototypal APIs that are patched or extended refer to instances with this.
(Statistics via http://trends.builtwith.com/javascript/jQuery and https://www.npmjs.com.)
You are likely to require dynamic this bindings already.
A lexical this is sometimes expected, but sometimes not; just as a dynamic this is sometimes expected, but sometimes not. Thankfully, there is a better way, which always produces and communicates the expected binding.
Regarding terse syntax
Arrow functions succeeded in providing a "shorter syntactical form" for functions. But will these shorter functions make you more successful?
Is x => x * x "easier to read" than function (x) { return x * x; }? Maybe it is, because it's more likely to produce a single, short line of code. According to Dyson's The influence of reading speed and line length on the effectiveness of reading from screen,
A medium line length (55 characters per line) appears to support effective reading at normal and fast speeds. This produced the highest level of comprehension . . .
Similar justifications are made for the conditional (ternary) operator, and for single-line if statements.
However, are you really writing the simple mathematical functions advertised in the proposal? My domains are not mathematical, so my subroutines are rarely so elegant. Rather, I commonly see arrow functions break a column limit, and wrap to another line due to the editor or style guide, which nullifies "readability" by Dyson's definition.
One might pose, "How about just using the short version for short functions, when possible?". But now a stylistic rule contradicts a language constraint: "Try to use the shortest function notation possible, keeping in mind that sometimes only the longest notation will bind this as expected." Such conflation makes arrows particularly prone to misuse.
There are numerous issues with arrow function syntax:
const a = x =>
doSomething(x);
const b = x =>
doSomething(x);
doSomethingElse(x);
Both of these functions are syntactically valid. But doSomethingElse(x); is not in the body of b. It is just a poorly-indented, top-level statement.
When expanding to the block form, there is no longer an implicit return, which one could forget to restore. But the expression may only have been intended to produce a side-effect, so who knows if an explicit return will be necessary going forward?
const create = () => User.create();
const create = () => {
let user;
User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
const create = () => {
let user;
return User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
What may be intended as a rest parameter can be parsed as the spread operator:
processData(data, ...results => {}) // Spread
processData(data, (...results) => {}) // Rest
Assignment can be confused with default arguments:
const a = 1;
let x;
const b = x => {}; // No default
const b = x = a => {}; // "Adding a default" instead creates a double assignment
const b = (x = a) => {}; // Remember to add parentheses
Blocks look like objects:
(id) => id // Returns `id`
(id) => {name: id} // Returns `undefined` (it's a labeled statement)
(id) => ({name: id}) // Returns an object
What does this mean?
() => {}
Did the author intend to create a no-op, or a function that returns an empty object? (With this in mind, should we ever place { after =>? Should we restrict ourselves to the expression syntax only? That would further reduce arrows' frequency.)
=> looks like <= and >=:
x => 1 ? 2 : 3
x <= 1 ? 2 : 3
if (x => 1) {}
if (x >= 1) {}
To invoke an arrow function expression immediately, one must place () on the outside, yet placing () on the inside is valid and could be intentional.
(() => doSomething()()) // Creates function calling value of `doSomething()`
(() => doSomething())() // Calls the arrow function
Although, if one writes (() => doSomething()()); with the intention of writing an immediately-invoked function expression, simply nothing will happen.
It's hard to argue that arrow functions are "more understandable" with all the above cases in mind. One could learn all the special rules required to utilize this syntax. Is it really worth it?
The syntax of function is unexceptionally generalized. To use function exclusively means the language itself prevents one from writing confusing code. To write procedures that should be syntactically understood in all cases, I choose function.
Regarding a guideline
You request a guideline that needs to be "clear" and "consistent." Using arrow functions will eventually result in syntactically-valid, logically-invalid code, with both function forms intertwined, meaningfully and arbitrarily. Therefore, I offer the following:
Guideline for Function Notation in ES6:
Always create procedures with function.
Always assign this to a variable. Do not use () => {}.

Arrow functions were created to simplify function scope and solving the this keyword by making it simpler. They utilize the => syntax, which looks like an arrow.
Note: It does not replace the existing functions. If you replace every function syntax with arrow functions, it's not going to work in all cases.
Let's have a look at the existing ES5 syntax. If the this keyword were inside an object’s method (a function that belongs to an object), what would it refer to?
var Actor = {
name: 'RajiniKanth',
getName: function() {
console.log(this.name);
}
};
Actor.getName();
The above snippet would refer to an object and print out the name "RajiniKanth". Let's explore the below snippet and see what would this point out here.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Now what about if the this keyword were inside of method’s function?
Here this would refer to window object than the inner function as its fallen out of scope. Because this, always references the owner of the function it is in, for this case — since it is now out of scope — the window/global object.
When it is inside of an object’s method — the function’s owner is the object. Thus the this keyword is bound to the object. Yet, when it is inside of a function, either stand alone or within another method, it will always refer to the window/global object.
var fn = function(){
alert(this);
}
fn(); // [object Window]
There are ways to solve this problem in our ES5 itself. Let us look into that before diving into ES6 arrow functions on how solve it.
Typically you would, create a variable outside of the method’s inner function. Now the ‘forEach’ method gains access to this and thus the object’s properties and their values.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
var _this = this;
this.movies.forEach(function(movie) {
alert(_this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Using bind to attach the this keyword that refers to the method to the method’s inner function.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
}.bind(this));
}
};
Actor.showMovies();
Now with the ES6 arrow function, we can deal with lexical scoping issue in a simpler way.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach((movie) => {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Arrow functions are more like function statements, except that they bind the this to the parent scope. If the arrow function is in the top scope, the this argument will refer to the window/global scope, while an arrow function inside a regular function will have its this argument the same as its outer function.
With arrow functions this is bound to the enclosing scope at creation time and cannot be changed. The new operator, bind, call, and apply have no effect on this.
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
// With a traditional function if we don't control
// the context then can we lose control of `this`.
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`
asyncFunction(o, function (param) {
// We made a mistake of thinking `this` is
// the instance of `o`.
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? false
In the above example, we lost the control of this. We can solve the above example by using a variable reference of this or using bind. With ES6, it becomes easier in managing the this as its bound to lexical scoping.
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`.
//
// Because this arrow function is created within
// the scope of `doSomething` it is bound to this
// lexical scope.
asyncFunction(o, (param) => {
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? true
When not to use arrow functions
Inside an object literal.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
getName: () => {
alert(this.name);
}
};
Actor.getName();
Actor.getName is defined with an arrow function, but on invocation it alerts undefined because this.name is undefined as the context remains to window.
It happens because the arrow function binds the context lexically with the window object... i.e., the outer scope. Executing this.name is equivalent to window.name, which is undefined.
Object prototype
The same rule applies when defining methods on a prototype object. Instead of using an arrow function for defining sayCatName method, which brings an incorrect context window:
function Actor(name) {
this.name = name;
}
Actor.prototype.getName = () => {
console.log(this === window); // => true
return this.name;
};
var act = new Actor('RajiniKanth');
act.getName(); // => undefined
Invoking constructors
this in a construction invocation is the newly created object. When executing new Fn(), the context of the constructor Fn is a new object: this instanceof Fn === true.
this is setup from the enclosing context, i.e., the outer scope which makes it not assigned to newly created object.
var Message = (text) => {
this.text = text;
};
// Throws "TypeError: Message is not a constructor"
var helloMessage = new Message('Hello World!');
Callback with dynamic context
Arrow function binds the context statically on declaration and is not possible to make it dynamic. Attaching event listeners to DOM elements is a common task in client side programming. An event triggers the handler function with this as the target element.
var button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
});
this is window in an arrow function that is defined in the global context. When a click event happens, the browser tries to invoke the handler function with button context, but arrow function does not change its pre-defined context. this.innerHTML is equivalent to window.innerHTML and has no sense.
You have to apply a function expression, which allows to change this depending on the target element:
var button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this === button); // => true
this.innerHTML = 'Clicked button';
});
When user clicks the button, this in the handler function is the button. Thus this.innerHTML = 'Clicked button' correctly modifies the button text to reflect the clicked status.
References
When 'Not' to Use Arrow Functions

Arrow functions - most widely used ES6 feature so far ...
Usage: All ES5 functions should be replaced with ES6 arrow functions except in following scenarios:
Arrow functions should not be used:
When we want function hoisting
as arrow functions are anonymous.
When we want to use this/arguments in a function
as arrow functions do not have this/arguments of their own, they depend upon their outer context.
When we want to use named function
as arrow functions are anonymous.
When we want to use function as a constructor
as arrow functions do not have their own this.
When we want to add function as a property in object literal and use object in it
as we can not access this (which should be object itself).
Let us understand some of the variants of arrow functions to understand better:
Variant 1: When we want to pass more than one argument to a function and return some value from it.
ES5 version:
var multiply = function (a, b) {
return a*b;
};
console.log(multiply(5, 6)); // 30
ES6 version:
var multiplyArrow = (a, b) => a*b;
console.log(multiplyArrow(5, 6)); // 30
Note:
The function keyword is not required.
=> is required.
{} are optional, when we do not provide {} return is implicitly added by JavaScript and when we do provide {} we need to add return if we need it.
Variant 2: When we want to pass only one argument to a function and return some value from it.
ES5 version:
var double = function(a) {
return a*2;
};
console.log(double(2)); // 4
ES6 version:
var doubleArrow = a => a*2;
console.log(doubleArrow(2)); // 4
Note:
When passing only one argument we can omit the parentheses, ().
Variant 3: When we do not want to pass any argument to a function and do not want to return any value.
ES5 version:
var sayHello = function() {
console.log("Hello");
};
sayHello(); // Hello
ES6 version:
var sayHelloArrow = () => {console.log("sayHelloArrow");}
sayHelloArrow(); // sayHelloArrow
Variant 4: When we want to explicitly return from arrow functions.
ES6 version:
var increment = x => {
return x + 1;
};
console.log(increment(1)); // 2
Variant 5: When we want to return an object from arrow functions.
ES6 version:
var returnObject = () => ({a:5});
console.log(returnObject());
Note:
We need to wrap the object in parentheses, (). Otherwise, JavaScript cannot differentiate between a block and an object.
Variant 6: Arrow functions do not have arguments (an array like object) of their own. They depend upon outer context for arguments.
ES6 version:
function foo() {
var abc = i => arguments[0];
console.log(abc(1));
};
foo(2); // 2
Note:
foo is an ES5 function, with an arguments array like object and an argument passed to it is 2 so arguments[0] for foo is 2.
abc is an ES6 arrow function since it does not have its own arguments. Hence it prints arguments[0] of foo its outer context instead.
Variant 7: Arrow functions do not have this of their own they depend upon outer context for this
ES5 version:
var obj5 = {
greet: "Hi, Welcome ",
greetUser : function(user) {
setTimeout(function(){
console.log(this.greet + ": " + user); // "this" here is undefined.
});
}
};
obj5.greetUser("Katty"); //undefined: Katty
Note:
The callback passed to setTimeout is an ES5 function and it has its own this which is undefined in a use-strict environment. Hence we get the output:
undefined: Katty
ES6 version:
var obj6 = {
greet: "Hi, Welcome ",
greetUser : function(user) {
setTimeout(() => console.log(this.greet + ": " + user));
// This here refers to outer context
}
};
obj6.greetUser("Katty"); // Hi, Welcome: Katty
Note:
The callback passed to setTimeout is an ES6 arrow function and it does not have its own this, so it takes it from its outer context that is greetUser which has this. That is obj6 and hence we get the output:
Hi, Welcome: Katty
Miscellaneous:
We cannot use new with arrow functions.
Arrow functions do not have prototype property.
We do not have binding of this when an arrow function is invoked through apply or call.

I still stand by everything I wrote in my first answer in this thread. However, my opinion on code style has developed since then, so I have a new answer to this question that builds on my last one.
Regarding lexical this
In my last answer, I deliberately eschewed an underlying belief I hold about this language, as it was not directly related to the argument I was making. Nonetheless, without this being explicitly stated, I can understand why many people simply balk at my recommendation to not use arrows, when they find arrows so useful.
My belief is this: we shouldn’t be using this in the first place. Therefore, if a person deliberately avoids using this in his code, then the “lexical this” feature of arrows is of little to no value. Also, under the premise that this is a bad thing, arrow’s treatment of this is less of a “good thing;” instead, it’s more of a form of damage control for another bad language feature.
I figure that this either does not occur to some people, but even to those to whom it does, they must invariably find themselves working within codebases where this appears a hundred times per file, and a little (or a lot) of damage control is all a reasonable person could hope for. So arrows can be good, in a way, when they make a bad situation better.
Even if it is easier to write code with this with arrows than without them, the rules for using arrows remain very complex (see: current thread). Thus, guidelines are neither “clear” nor “consistent,” as you’ve requested. Even if programmers know about arrows’ ambiguities, I think they shrug and accept them anyway, because the value of lexical this overshadows them.
All this is a preface to the following realization: if one does not use this, then the ambiguity about this that arrows normally cause becomes irrelevant. Arrows become more neutral in this context.
Regarding terse syntax
When I wrote my first answer, I was of the opinion that even slavish adherence to best practices was a worthwhile price to pay if it meant I could produce more perfect code. But I eventually came to realize that terseness can serve as a form of abstraction that can improve code quality, too — enough so to justify straying from best practices sometimes.
In other words: dammit, I want one-liner functions, too!
Regarding a guideline
With the possibility of this-neutral arrow functions, and terseness being worth pursuit, I offer the following more lenient guideline:
Guideline for Function Notation in ES6:
Don’t use this.
Use function declarations for functions you’d call by name (because they’re hoisted).
Use arrow functions for callbacks (because they tend to be terser).

In addition to the great answers so far, I'd like to present a very different reason why arrow functions are in a certain sense fundamentally better than "ordinary" JavaScript functions.
For the sake of discussion, let's temporarily assume we use a type checker like TypeScript or Facebook's "Flow". Consider the following toy module, which is valid ECMAScript 6 code plus Flow type annotations (I'll include the untyped code, which would realistically result from Babel, at the end of this answer, so it can actually be run):
export class C {
n : number;
f1: number => number;
f2: number => number;
constructor(){
this.n = 42;
this.f1 = (x:number) => x + this.n;
this.f2 = function (x:number) { return x + this.n;};
}
}
Now see what happens when we use the class C from a different module, like this:
let o = { f1: new C().f1, f2: new C().f2, n: "foo" };
let n1: number = o.f1(1); // n1 = 43
console.log(n1 === 43); // true
let n2: number = o.f2(1); // n2 = "1foo"
console.log(n2 === "1foo"); // true, not a string!
As you can see, the type checker failed here: f2 was supposed to return a number, but it returned a string!
Worse, it seems that no conceivable type checker can handle ordinary (non-arrow) JavaScript functions, because the "this" of f2 does not occur in the argument list of f2, so the required type for "this" could not possibly be added as an annotation to f2.
Does this problem also affect people who don't use type checkers? I think so, because even when we have no static types, we think as if they're there. ("The first parameters must be a number, the second one a string" etc.) A hidden "this"-argument which may or may not be used in the function's body makes our mental bookkeeping harder.
Here is the runnable untyped version, which would be produced by Babel:
class C {
constructor() {
this.n = 42;
this.f1 = x => x + this.n;
this.f2 = function (x) { return x + this.n; };
}
}
let o = { f1: new C().f1, f2: new C().f2, n: "foo" };
let n1 = o.f1(1); // n1 = 43
console.log(n1 === 43); // true
let n2 = o.f2(1); // n2 = "1foo"
console.log(n2 === "1foo"); // true, not a string!

I prefer to use arrow functions at all times where access to local this is not needed, because arrow functions do not bind their own this, arguments, super, or new.target.

Arrow functions or lambdas, were introduced in ES 6. Apart from its elegance in minimal syntax, the most notable functional difference is scoping of this inside an arrow function
In regular function expressions, the this keyword is bound to different values based on the context in which it is called.
In arrow functions, this is lexically bound, which means it closes over this from the scope in which the arrow function was defined (parent-scope), and does not change no matter where and how it is invoked / called.
Limitations of arrow functions as methods on an object
// this = global Window
let objA = {
id: 10,
name: "Simar",
print () { // same as print: function()
console.log(`[${this.id} -> ${this.name}]`);
}
}
objA.print(); // logs: [10 -> Simar]
objA = {
id: 10,
name: "Simar",
print: () => {
// Closes over this lexically (global Window)
console.log(`[${this.id} -> ${this.name}]`);
}
};
objA.print(); // logs: [undefined -> undefined]
In the case of objA.print() when print() method defined using regular function, it worked by resolving this properly to objA for method invocation, but failed when defined as an arrow=> function. It is because this in a regular function when invoked as a method on an object (objA), is the object itself.
However, in case of an arrow function, this gets lexically bound to the the this of the enclosing scope where it was defined (global / Window in our case) and stays it stays same during its invocation as a method on objA.
There are advantages of an arrow-functions over regular functions in method(s) of an object, but only when this is expected to be fixed and bound at the time of definition.
/* this = global | Window (enclosing scope) */
let objB = {
id: 20,
name: "Paul",
print () { // Same as print: function()
setTimeout( function() {
// Invoked async, not bound to objB
console.log(`[${this.id} -> ${this.name}]`);
}, 1)
}
};
objB.print(); // Logs: [undefined -> undefined]'
objB = {
id: 20,
name: "Paul",
print () { // Same as print: function()
setTimeout( () => {
// Closes over bind to this from objB.print()
console.log(`[${this.id} -> ${this.name}]`);
}, 1)
}
};
objB.print(); // Logs: [20 -> Paul]
In the case of objB.print() where the print() method is defined as function that invokes console.log([${this.id} -> {this.name}]) asynchronously as a call-back on setTimeout , this resolved correctly to objB when an arrow function was used as call-back, but failed when the call-back was defined as as regular function.
It is because the arrow => function, passed to setTimeout(()=>..), closed over this lexically from its parent, i.e., invocation of objB.print() which defined it. In other words, the arrow => function passed in to to setTimeout(()==>... bound to objB as its this because the invocation of objB.print() this was objB itself.
We could easily use Function.prototype.bind() to make the call-back defined as a regular function work, by binding it to the correct this.
const objB = {
id: 20,
name: "Singh",
print () { // The same as print: function()
setTimeout( (function() {
console.log(`[${this.id} -> ${this.name}]`);
}).bind(this), 1)
}
}
objB.print() // logs: [20 -> Singh]
However, arrow functions come in handy and are less error prone for the case of async call-backs where we know the this at the time of the functions definition to which it gets and should be bound.
Limitation of Arrow-Functions where this needs to change across invocations
Anytime, we need a function whose this can be changed at the time of invocation, we can’t use arrow functions.
/* this = global | Window (enclosing scope) */
function print() {
console.log(`[${this.id} -> {this.name}]`);
}
const obj1 = {
id: 10,
name: "Simar",
print // The same as print: print
};
obj.print(); // Logs: [10 -> Simar]
const obj2 = {
id: 20,
name: "Paul",
};
printObj2 = obj2.bind(obj2);
printObj2(); // Logs: [20 -> Paul]
print.call(obj2); // logs: [20 -> Paul]
None of the above will work with arrow function const print = () => { console.log([${this.id} -> {this.name}]);} as this can’t be changed and will stay bound to the this of the enclosing scope where it was defined (global / Window).
In all these examples, we invoked the same function with different objects (obj1 and obj2) one after the another, both of which were created after the print() function was declared.
These were contrived examples, but let’s think about some more real life examples. If we had to write our reduce() method similar to one that works on arrays , we again can’t define it as a lambda, because it needs to infer this from the invocation context, i.e., the array on which it was invoked.
For this reason, constructor functions can never be defined as arrow functions, as this for a constructor function can not be set at the time of its declaration. Every time a constructor function is invoked with the new keyword, a new object is created which then gets bound to that particular invocation.
Also when when frameworks or systems accept a callback function(s) to be invoked later with dynamic context this , we can’t use arrow functions as again this may need to change with every invocation. This situation commonly arises with DOM event handlers.
'use strict'
var button = document.getElementById('button');
button.addEventListener('click', function {
// web-api invokes with this bound to current-target in DOM
this.classList.toggle('on');
});
var button = document.getElementById('button');
button.addEventListener('click', () => {
// TypeError; 'use strict' -> no global this
this.classList.toggle('on');
});
This is also the reason why in frameworks like Angular 2+ and Vue.js expect the template-component binding methods to be regular function / methods as this for their invocation is managed by the frameworks for the binding functions. (Angular uses Zone.js to manage an async context for invocations of view-template binding functions.)
On the other hand, in React, when we want pass a component's method as an event-handler, for example, <input onChange={this.handleOnchange} />, we should define handleOnchanage = (event)=> {this.props.onInputChange(event.target.value);} as an arrow function as for every invocation. We want this to be the same instance of the component that produced the JSX for the rendered DOM element.
This article is also available in my Medium publication. If you like the article, or have any comments and suggestions, please clap or leave comments on Medium.

In a simple way,
var a = 20; function a() {this.a = 10; console.log(a);}
//20, since the context here is window.
Another instance:
var a = 20;
function ex(){
this.a = 10;
function inner(){
console.log(this.a); // Can you guess the output of this line?
}
inner();
}
var test = new ex();
Ans: The console would print 20.
The reason being whenever a function is executed its own stack is created, in this example the ex function is executed with the new operator so a context will be created, and when inner is executed it JavaScript would create a new stack and execute the inner function in a global context though there is a local context.
So, if we want the inner function to have a local context, which is ex, then we need to bind the context to the inner function.
Arrows solve this problem. Instead of taking the Global context, they take the local context if any exist. In the *given example, it will take new ex() as this.
So, in all cases where binding is explicit, arrows solve the problem by defaults.

Related

Javascript: Uncaught TypeError: this.x is not a function but it is defined [duplicate]

With () => {} and function () {} we are getting two very similar ways to write functions in ES6. In other languages lambda functions often distinguish themselves by being anonymous, but in ECMAScript any function can be anonymous. Each of the two types have unique usage domains (namely when this needs to either be bound explicitly or explicitly not be bound). Between those domains there are a vast number of cases where either notation will do.
Arrow functions in ES6 have at least two limitations:
Don't work with new and cannot be used when creating prototype
Fixed this bound to scope at initialisation
These two limitations aside, arrow functions could theoretically replace regular functions almost anywhere. What is the right approach using them in practice? Should arrow functions be used e.g.:
"everywhere they work", i.e. everywhere a function does not have to be agnostic about the this variable and we are not creating an object.
only "everywhere they are needed", i.e. event listeners, timeouts, that need to be bound to a certain scope
with 'short' functions, but not with 'long' functions
only with functions that do not contain another arrow function
I am looking for a guideline to selecting the appropriate function notation in the future version of ECMAScript. The guideline will need to be clear, so that it can be taught to developers in a team, and to be consistent so that it does not require constant refactoring back and forth from one function notation to another.
The question is directed at people who have thought about code style in the context of the upcoming ECMAScript 6 (Harmony) and who have already worked with the language.
A while ago our team migrated all its code (a mid-sized AngularJS app) to JavaScript compiled using Traceur Babel. I'm now using the following rule of thumb for functions in ES6 and beyond:
Use function in the global scope and for Object.prototype properties.
Use class for object constructors.
Use => everywhere else.
Why use arrow functions almost everywhere?
Scope safety: When arrow functions are used consistently, everything is guaranteed to use the same thisObject as the root. If even a single standard function callback is mixed in with a bunch of arrow functions there's a chance the scope will become messed up.
Compactness: Arrow functions are easier to read and write. (This may seem opinionated so I will give a few examples further on.)
Clarity: When almost everything is an arrow function, any regular function immediately sticks out for defining the scope. A developer can always look up the next-higher function statement to see what the thisObject is.
Why always use regular functions on the global scope or module scope?
To indicate a function that should not access the thisObject.
The window object (global scope) is best addressed explicitly.
Many Object.prototype definitions live in the global scope (think String.prototype.truncate, etc.) and those generally have to be of type function anyway. Consistently using function on the global scope helps avoid errors.
Many functions in the global scope are object constructors for old-style class definitions.
Functions can be named1. This has two benefits: (1) It is less awkward to writefunction foo(){} than const foo = () => {} — in particular outside other function calls. (2) The function name shows in stack traces. While it would be tedious to name every internal callback, naming all the public functions is probably a good idea.
Function declarations are hoisted, (meaning they can be accessed before they are declared), which is a useful attribute in a static utility function.
Object constructors
Attempting to instantiate an arrow function throws an exception:
var x = () => {};
new x(); // TypeError: x is not a constructor
One key advantage of functions over arrow functions is therefore that functions double as object constructors:
function Person(name) {
this.name = name;
}
However, the functionally identical2 ECMAScript Harmony draft class definition is almost as compact:
class Person {
constructor(name) {
this.name = name;
}
}
I expect that use of the former notation will eventually be discouraged. The object constructor notation may still be used by some for simple anonymous object factories where objects are programmatically generated, but not for much else.
Where an object constructor is needed one should consider converting the function to a class as shown above. The syntax works with anonymous functions/classes as well.
Readability of arrow functions
The probably best argument for sticking to regular functions - scope safety be damned - would be that arrow functions are less readable than regular functions. If your code is not functional in the first place, then arrow functions may not seem necessary, and when arrow functions are not used consistently they look ugly.
ECMAScript has changed quite a bit since ECMAScript 5.1 gave us the functional Array.forEach, Array.map and all of these functional programming features that have us use functions where for loops would have been used before. Asynchronous JavaScript has taken off quite a bit. ES6 will also ship a Promise object, which means even more anonymous functions. There is no going back for functional programming. In functional JavaScript, arrow functions are preferable over regular functions.
Take for instance this (particularly confusing) piece of code3:
function CommentController(articles) {
this.comments = [];
articles.getList()
.then(articles => Promise.all(articles.map(article => article.comments.getList())))
.then(commentLists => commentLists.reduce((a, b) => a.concat(b)));
.then(comments => {
this.comments = comments;
})
}
The same piece of code with regular functions:
function CommentController(articles) {
this.comments = [];
articles.getList()
.then(function (articles) {
return Promise.all(articles.map(function (article) {
return article.comments.getList();
}));
})
.then(function (commentLists) {
return commentLists.reduce(function (a, b) {
return a.concat(b);
});
})
.then(function (comments) {
this.comments = comments;
}.bind(this));
}
While any one of the arrow functions can be replaced by a standard function, there would be very little to gain from doing so. Which version is more readable? I would say the first one.
I think the question whether to use arrow functions or regular functions will become less relevant over time. Most functions will either become class methods, which make away with the function keyword, or they will become classes. Functions will remain in use for patching classes through the Object.prototype. In the mean time I suggest reserving the function keyword for anything that should really be a class method or a class.
Notes
Named arrow functions have been deferred in the ES6 specification. They might still be added a future version.
According to the draft specification, "Class declarations/expressions create a constructor function/prototype pair exactly as for function declarations" as long as a class does not use the extend keyword. A minor difference is that class declarations are constants, whereas function declarations are not.
Note on blocks in single statement arrow functions: I like to use a block wherever an arrow function is called for the side effect alone (e.g., assignment). That way it is clear that the return value can be discarded.
According to the proposal, arrows aimed "to address and resolve several common pain points of traditional function expressions". They intended to improve matters by binding this lexically and offering terse syntax.
However,
One cannot consistently bind this lexically
Arrow function syntax is delicate and ambiguous
Therefore, arrow functions create opportunities for confusion and errors, and should be excluded from a JavaScript programmer's vocabulary, replaced with function exclusively.
Regarding lexical this
this is problematic:
function Book(settings) {
this.settings = settings;
this.pages = this.createPages();
}
Book.prototype.render = function () {
this.pages.forEach(function (page) {
page.draw(this.settings);
}, this);
};
Arrow functions intend to fix the problem where we need to access a property of this inside a callback. There are already several ways to do that: One could assign this to a variable, use bind, or use the third argument available on the Array aggregate methods. Yet arrows seem to be the simplest workaround, so the method could be refactored like this:
this.pages.forEach(page => page.draw(this.settings));
However, consider if the code used a library like jQuery, whose methods bind this specially. Now, there are two this values to deal with:
Book.prototype.render = function () {
var book = this;
this.$pages.each(function (index) {
var $page = $(this);
book.draw(book.currentPage + index, $page);
});
};
We must use function in order for each to bind this dynamically. We can't use an arrow function here.
Dealing with multiple this values can also be confusing, because it's hard to know which this an author was talking about:
function Reader() {
this.book.on('change', function () {
this.reformat();
});
}
Did the author actually intend to call Book.prototype.reformat? Or did he forget to bind this, and intend to call Reader.prototype.reformat? If we change the handler to an arrow function, we will similarly wonder if the author wanted the dynamic this, yet chose an arrow because it fit on one line:
function Reader() {
this.book.on('change', () => this.reformat());
}
One may pose: "Is it exceptional that arrows could sometimes be the wrong function to use? Perhaps if we only rarely need dynamic this values, then it would still be okay to use arrows most of the time."
But ask yourself this: "Would it be 'worth it' to debug code and find that the result of an error was brought upon by an 'edge case?'" I'd prefer to avoid trouble not just most of the time, but 100% of the time.
There is a better way: Always use function (so this can always be dynamically bound), and always reference this via a variable. Variables are lexical and assume many names. Assigning this to a variable will make your intentions clear:
function Reader() {
var reader = this;
reader.book.on('change', function () {
var book = this;
book.reformat();
reader.reformat();
});
}
Furthermore, always assigning this to a variable (even when there is a single this or no other functions) ensures one's intentions remain clear even after the code is changed.
Also, dynamic this is hardly exceptional. jQuery is used on over 50 million websites (as of this writing in February 2016). Here are other APIs binding this dynamically:
Mocha (~120k downloads yesterday) exposes methods for its tests via this.
Grunt (~63k downloads yesterday) exposes methods for build tasks via this.
Backbone (~22k downloads yesterday) defines methods accessing this.
Event APIs (like the DOM's) refer to an EventTarget with this.
Prototypal APIs that are patched or extended refer to instances with this.
(Statistics via http://trends.builtwith.com/javascript/jQuery and https://www.npmjs.com.)
You are likely to require dynamic this bindings already.
A lexical this is sometimes expected, but sometimes not; just as a dynamic this is sometimes expected, but sometimes not. Thankfully, there is a better way, which always produces and communicates the expected binding.
Regarding terse syntax
Arrow functions succeeded in providing a "shorter syntactical form" for functions. But will these shorter functions make you more successful?
Is x => x * x "easier to read" than function (x) { return x * x; }? Maybe it is, because it's more likely to produce a single, short line of code. According to Dyson's The influence of reading speed and line length on the effectiveness of reading from screen,
A medium line length (55 characters per line) appears to support effective reading at normal and fast speeds. This produced the highest level of comprehension . . .
Similar justifications are made for the conditional (ternary) operator, and for single-line if statements.
However, are you really writing the simple mathematical functions advertised in the proposal? My domains are not mathematical, so my subroutines are rarely so elegant. Rather, I commonly see arrow functions break a column limit, and wrap to another line due to the editor or style guide, which nullifies "readability" by Dyson's definition.
One might pose, "How about just using the short version for short functions, when possible?". But now a stylistic rule contradicts a language constraint: "Try to use the shortest function notation possible, keeping in mind that sometimes only the longest notation will bind this as expected." Such conflation makes arrows particularly prone to misuse.
There are numerous issues with arrow function syntax:
const a = x =>
doSomething(x);
const b = x =>
doSomething(x);
doSomethingElse(x);
Both of these functions are syntactically valid. But doSomethingElse(x); is not in the body of b. It is just a poorly-indented, top-level statement.
When expanding to the block form, there is no longer an implicit return, which one could forget to restore. But the expression may only have been intended to produce a side-effect, so who knows if an explicit return will be necessary going forward?
const create = () => User.create();
const create = () => {
let user;
User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
const create = () => {
let user;
return User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
What may be intended as a rest parameter can be parsed as the spread operator:
processData(data, ...results => {}) // Spread
processData(data, (...results) => {}) // Rest
Assignment can be confused with default arguments:
const a = 1;
let x;
const b = x => {}; // No default
const b = x = a => {}; // "Adding a default" instead creates a double assignment
const b = (x = a) => {}; // Remember to add parentheses
Blocks look like objects:
(id) => id // Returns `id`
(id) => {name: id} // Returns `undefined` (it's a labeled statement)
(id) => ({name: id}) // Returns an object
What does this mean?
() => {}
Did the author intend to create a no-op, or a function that returns an empty object? (With this in mind, should we ever place { after =>? Should we restrict ourselves to the expression syntax only? That would further reduce arrows' frequency.)
=> looks like <= and >=:
x => 1 ? 2 : 3
x <= 1 ? 2 : 3
if (x => 1) {}
if (x >= 1) {}
To invoke an arrow function expression immediately, one must place () on the outside, yet placing () on the inside is valid and could be intentional.
(() => doSomething()()) // Creates function calling value of `doSomething()`
(() => doSomething())() // Calls the arrow function
Although, if one writes (() => doSomething()()); with the intention of writing an immediately-invoked function expression, simply nothing will happen.
It's hard to argue that arrow functions are "more understandable" with all the above cases in mind. One could learn all the special rules required to utilize this syntax. Is it really worth it?
The syntax of function is unexceptionally generalized. To use function exclusively means the language itself prevents one from writing confusing code. To write procedures that should be syntactically understood in all cases, I choose function.
Regarding a guideline
You request a guideline that needs to be "clear" and "consistent." Using arrow functions will eventually result in syntactically-valid, logically-invalid code, with both function forms intertwined, meaningfully and arbitrarily. Therefore, I offer the following:
Guideline for Function Notation in ES6:
Always create procedures with function.
Always assign this to a variable. Do not use () => {}.
Arrow functions were created to simplify function scope and solving the this keyword by making it simpler. They utilize the => syntax, which looks like an arrow.
Note: It does not replace the existing functions. If you replace every function syntax with arrow functions, it's not going to work in all cases.
Let's have a look at the existing ES5 syntax. If the this keyword were inside an object’s method (a function that belongs to an object), what would it refer to?
var Actor = {
name: 'RajiniKanth',
getName: function() {
console.log(this.name);
}
};
Actor.getName();
The above snippet would refer to an object and print out the name "RajiniKanth". Let's explore the below snippet and see what would this point out here.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Now what about if the this keyword were inside of method’s function?
Here this would refer to window object than the inner function as its fallen out of scope. Because this, always references the owner of the function it is in, for this case — since it is now out of scope — the window/global object.
When it is inside of an object’s method — the function’s owner is the object. Thus the this keyword is bound to the object. Yet, when it is inside of a function, either stand alone or within another method, it will always refer to the window/global object.
var fn = function(){
alert(this);
}
fn(); // [object Window]
There are ways to solve this problem in our ES5 itself. Let us look into that before diving into ES6 arrow functions on how solve it.
Typically you would, create a variable outside of the method’s inner function. Now the ‘forEach’ method gains access to this and thus the object’s properties and their values.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
var _this = this;
this.movies.forEach(function(movie) {
alert(_this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Using bind to attach the this keyword that refers to the method to the method’s inner function.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
}.bind(this));
}
};
Actor.showMovies();
Now with the ES6 arrow function, we can deal with lexical scoping issue in a simpler way.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach((movie) => {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Arrow functions are more like function statements, except that they bind the this to the parent scope. If the arrow function is in the top scope, the this argument will refer to the window/global scope, while an arrow function inside a regular function will have its this argument the same as its outer function.
With arrow functions this is bound to the enclosing scope at creation time and cannot be changed. The new operator, bind, call, and apply have no effect on this.
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
// With a traditional function if we don't control
// the context then can we lose control of `this`.
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`
asyncFunction(o, function (param) {
// We made a mistake of thinking `this` is
// the instance of `o`.
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? false
In the above example, we lost the control of this. We can solve the above example by using a variable reference of this or using bind. With ES6, it becomes easier in managing the this as its bound to lexical scoping.
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`.
//
// Because this arrow function is created within
// the scope of `doSomething` it is bound to this
// lexical scope.
asyncFunction(o, (param) => {
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? true
When not to use arrow functions
Inside an object literal.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
getName: () => {
alert(this.name);
}
};
Actor.getName();
Actor.getName is defined with an arrow function, but on invocation it alerts undefined because this.name is undefined as the context remains to window.
It happens because the arrow function binds the context lexically with the window object... i.e., the outer scope. Executing this.name is equivalent to window.name, which is undefined.
Object prototype
The same rule applies when defining methods on a prototype object. Instead of using an arrow function for defining sayCatName method, which brings an incorrect context window:
function Actor(name) {
this.name = name;
}
Actor.prototype.getName = () => {
console.log(this === window); // => true
return this.name;
};
var act = new Actor('RajiniKanth');
act.getName(); // => undefined
Invoking constructors
this in a construction invocation is the newly created object. When executing new Fn(), the context of the constructor Fn is a new object: this instanceof Fn === true.
this is setup from the enclosing context, i.e., the outer scope which makes it not assigned to newly created object.
var Message = (text) => {
this.text = text;
};
// Throws "TypeError: Message is not a constructor"
var helloMessage = new Message('Hello World!');
Callback with dynamic context
Arrow function binds the context statically on declaration and is not possible to make it dynamic. Attaching event listeners to DOM elements is a common task in client side programming. An event triggers the handler function with this as the target element.
var button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
});
this is window in an arrow function that is defined in the global context. When a click event happens, the browser tries to invoke the handler function with button context, but arrow function does not change its pre-defined context. this.innerHTML is equivalent to window.innerHTML and has no sense.
You have to apply a function expression, which allows to change this depending on the target element:
var button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this === button); // => true
this.innerHTML = 'Clicked button';
});
When user clicks the button, this in the handler function is the button. Thus this.innerHTML = 'Clicked button' correctly modifies the button text to reflect the clicked status.
References
When 'Not' to Use Arrow Functions
Arrow functions - most widely used ES6 feature so far ...
Usage: All ES5 functions should be replaced with ES6 arrow functions except in following scenarios:
Arrow functions should not be used:
When we want function hoisting
as arrow functions are anonymous.
When we want to use this/arguments in a function
as arrow functions do not have this/arguments of their own, they depend upon their outer context.
When we want to use named function
as arrow functions are anonymous.
When we want to use function as a constructor
as arrow functions do not have their own this.
When we want to add function as a property in object literal and use object in it
as we can not access this (which should be object itself).
Let us understand some of the variants of arrow functions to understand better:
Variant 1: When we want to pass more than one argument to a function and return some value from it.
ES5 version:
var multiply = function (a, b) {
return a*b;
};
console.log(multiply(5, 6)); // 30
ES6 version:
var multiplyArrow = (a, b) => a*b;
console.log(multiplyArrow(5, 6)); // 30
Note:
The function keyword is not required.
=> is required.
{} are optional, when we do not provide {} return is implicitly added by JavaScript and when we do provide {} we need to add return if we need it.
Variant 2: When we want to pass only one argument to a function and return some value from it.
ES5 version:
var double = function(a) {
return a*2;
};
console.log(double(2)); // 4
ES6 version:
var doubleArrow = a => a*2;
console.log(doubleArrow(2)); // 4
Note:
When passing only one argument we can omit the parentheses, ().
Variant 3: When we do not want to pass any argument to a function and do not want to return any value.
ES5 version:
var sayHello = function() {
console.log("Hello");
};
sayHello(); // Hello
ES6 version:
var sayHelloArrow = () => {console.log("sayHelloArrow");}
sayHelloArrow(); // sayHelloArrow
Variant 4: When we want to explicitly return from arrow functions.
ES6 version:
var increment = x => {
return x + 1;
};
console.log(increment(1)); // 2
Variant 5: When we want to return an object from arrow functions.
ES6 version:
var returnObject = () => ({a:5});
console.log(returnObject());
Note:
We need to wrap the object in parentheses, (). Otherwise, JavaScript cannot differentiate between a block and an object.
Variant 6: Arrow functions do not have arguments (an array like object) of their own. They depend upon outer context for arguments.
ES6 version:
function foo() {
var abc = i => arguments[0];
console.log(abc(1));
};
foo(2); // 2
Note:
foo is an ES5 function, with an arguments array like object and an argument passed to it is 2 so arguments[0] for foo is 2.
abc is an ES6 arrow function since it does not have its own arguments. Hence it prints arguments[0] of foo its outer context instead.
Variant 7: Arrow functions do not have this of their own they depend upon outer context for this
ES5 version:
var obj5 = {
greet: "Hi, Welcome ",
greetUser : function(user) {
setTimeout(function(){
console.log(this.greet + ": " + user); // "this" here is undefined.
});
}
};
obj5.greetUser("Katty"); //undefined: Katty
Note:
The callback passed to setTimeout is an ES5 function and it has its own this which is undefined in a use-strict environment. Hence we get the output:
undefined: Katty
ES6 version:
var obj6 = {
greet: "Hi, Welcome ",
greetUser : function(user) {
setTimeout(() => console.log(this.greet + ": " + user));
// This here refers to outer context
}
};
obj6.greetUser("Katty"); // Hi, Welcome: Katty
Note:
The callback passed to setTimeout is an ES6 arrow function and it does not have its own this, so it takes it from its outer context that is greetUser which has this. That is obj6 and hence we get the output:
Hi, Welcome: Katty
Miscellaneous:
We cannot use new with arrow functions.
Arrow functions do not have prototype property.
We do not have binding of this when an arrow function is invoked through apply or call.
I still stand by everything I wrote in my first answer in this thread. However, my opinion on code style has developed since then, so I have a new answer to this question that builds on my last one.
Regarding lexical this
In my last answer, I deliberately eschewed an underlying belief I hold about this language, as it was not directly related to the argument I was making. Nonetheless, without this being explicitly stated, I can understand why many people simply balk at my recommendation to not use arrows, when they find arrows so useful.
My belief is this: we shouldn’t be using this in the first place. Therefore, if a person deliberately avoids using this in his code, then the “lexical this” feature of arrows is of little to no value. Also, under the premise that this is a bad thing, arrow’s treatment of this is less of a “good thing;” instead, it’s more of a form of damage control for another bad language feature.
I figure that this either does not occur to some people, but even to those to whom it does, they must invariably find themselves working within codebases where this appears a hundred times per file, and a little (or a lot) of damage control is all a reasonable person could hope for. So arrows can be good, in a way, when they make a bad situation better.
Even if it is easier to write code with this with arrows than without them, the rules for using arrows remain very complex (see: current thread). Thus, guidelines are neither “clear” nor “consistent,” as you’ve requested. Even if programmers know about arrows’ ambiguities, I think they shrug and accept them anyway, because the value of lexical this overshadows them.
All this is a preface to the following realization: if one does not use this, then the ambiguity about this that arrows normally cause becomes irrelevant. Arrows become more neutral in this context.
Regarding terse syntax
When I wrote my first answer, I was of the opinion that even slavish adherence to best practices was a worthwhile price to pay if it meant I could produce more perfect code. But I eventually came to realize that terseness can serve as a form of abstraction that can improve code quality, too — enough so to justify straying from best practices sometimes.
In other words: dammit, I want one-liner functions, too!
Regarding a guideline
With the possibility of this-neutral arrow functions, and terseness being worth pursuit, I offer the following more lenient guideline:
Guideline for Function Notation in ES6:
Don’t use this.
Use function declarations for functions you’d call by name (because they’re hoisted).
Use arrow functions for callbacks (because they tend to be terser).
In addition to the great answers so far, I'd like to present a very different reason why arrow functions are in a certain sense fundamentally better than "ordinary" JavaScript functions.
For the sake of discussion, let's temporarily assume we use a type checker like TypeScript or Facebook's "Flow". Consider the following toy module, which is valid ECMAScript 6 code plus Flow type annotations (I'll include the untyped code, which would realistically result from Babel, at the end of this answer, so it can actually be run):
export class C {
n : number;
f1: number => number;
f2: number => number;
constructor(){
this.n = 42;
this.f1 = (x:number) => x + this.n;
this.f2 = function (x:number) { return x + this.n;};
}
}
Now see what happens when we use the class C from a different module, like this:
let o = { f1: new C().f1, f2: new C().f2, n: "foo" };
let n1: number = o.f1(1); // n1 = 43
console.log(n1 === 43); // true
let n2: number = o.f2(1); // n2 = "1foo"
console.log(n2 === "1foo"); // true, not a string!
As you can see, the type checker failed here: f2 was supposed to return a number, but it returned a string!
Worse, it seems that no conceivable type checker can handle ordinary (non-arrow) JavaScript functions, because the "this" of f2 does not occur in the argument list of f2, so the required type for "this" could not possibly be added as an annotation to f2.
Does this problem also affect people who don't use type checkers? I think so, because even when we have no static types, we think as if they're there. ("The first parameters must be a number, the second one a string" etc.) A hidden "this"-argument which may or may not be used in the function's body makes our mental bookkeeping harder.
Here is the runnable untyped version, which would be produced by Babel:
class C {
constructor() {
this.n = 42;
this.f1 = x => x + this.n;
this.f2 = function (x) { return x + this.n; };
}
}
let o = { f1: new C().f1, f2: new C().f2, n: "foo" };
let n1 = o.f1(1); // n1 = 43
console.log(n1 === 43); // true
let n2 = o.f2(1); // n2 = "1foo"
console.log(n2 === "1foo"); // true, not a string!
I prefer to use arrow functions at all times where access to local this is not needed, because arrow functions do not bind their own this, arguments, super, or new.target.
Arrow functions or lambdas, were introduced in ES 6. Apart from its elegance in minimal syntax, the most notable functional difference is scoping of this inside an arrow function
In regular function expressions, the this keyword is bound to different values based on the context in which it is called.
In arrow functions, this is lexically bound, which means it closes over this from the scope in which the arrow function was defined (parent-scope), and does not change no matter where and how it is invoked / called.
Limitations of arrow functions as methods on an object
// this = global Window
let objA = {
id: 10,
name: "Simar",
print () { // same as print: function()
console.log(`[${this.id} -> ${this.name}]`);
}
}
objA.print(); // logs: [10 -> Simar]
objA = {
id: 10,
name: "Simar",
print: () => {
// Closes over this lexically (global Window)
console.log(`[${this.id} -> ${this.name}]`);
}
};
objA.print(); // logs: [undefined -> undefined]
In the case of objA.print() when print() method defined using regular function, it worked by resolving this properly to objA for method invocation, but failed when defined as an arrow=> function. It is because this in a regular function when invoked as a method on an object (objA), is the object itself.
However, in case of an arrow function, this gets lexically bound to the the this of the enclosing scope where it was defined (global / Window in our case) and stays it stays same during its invocation as a method on objA.
There are advantages of an arrow-functions over regular functions in method(s) of an object, but only when this is expected to be fixed and bound at the time of definition.
/* this = global | Window (enclosing scope) */
let objB = {
id: 20,
name: "Paul",
print () { // Same as print: function()
setTimeout( function() {
// Invoked async, not bound to objB
console.log(`[${this.id} -> ${this.name}]`);
}, 1)
}
};
objB.print(); // Logs: [undefined -> undefined]'
objB = {
id: 20,
name: "Paul",
print () { // Same as print: function()
setTimeout( () => {
// Closes over bind to this from objB.print()
console.log(`[${this.id} -> ${this.name}]`);
}, 1)
}
};
objB.print(); // Logs: [20 -> Paul]
In the case of objB.print() where the print() method is defined as function that invokes console.log([${this.id} -> {this.name}]) asynchronously as a call-back on setTimeout , this resolved correctly to objB when an arrow function was used as call-back, but failed when the call-back was defined as as regular function.
It is because the arrow => function, passed to setTimeout(()=>..), closed over this lexically from its parent, i.e., invocation of objB.print() which defined it. In other words, the arrow => function passed in to to setTimeout(()==>... bound to objB as its this because the invocation of objB.print() this was objB itself.
We could easily use Function.prototype.bind() to make the call-back defined as a regular function work, by binding it to the correct this.
const objB = {
id: 20,
name: "Singh",
print () { // The same as print: function()
setTimeout( (function() {
console.log(`[${this.id} -> ${this.name}]`);
}).bind(this), 1)
}
}
objB.print() // logs: [20 -> Singh]
However, arrow functions come in handy and are less error prone for the case of async call-backs where we know the this at the time of the functions definition to which it gets and should be bound.
Limitation of Arrow-Functions where this needs to change across invocations
Anytime, we need a function whose this can be changed at the time of invocation, we can’t use arrow functions.
/* this = global | Window (enclosing scope) */
function print() {
console.log(`[${this.id} -> {this.name}]`);
}
const obj1 = {
id: 10,
name: "Simar",
print // The same as print: print
};
obj.print(); // Logs: [10 -> Simar]
const obj2 = {
id: 20,
name: "Paul",
};
printObj2 = obj2.bind(obj2);
printObj2(); // Logs: [20 -> Paul]
print.call(obj2); // logs: [20 -> Paul]
None of the above will work with arrow function const print = () => { console.log([${this.id} -> {this.name}]);} as this can’t be changed and will stay bound to the this of the enclosing scope where it was defined (global / Window).
In all these examples, we invoked the same function with different objects (obj1 and obj2) one after the another, both of which were created after the print() function was declared.
These were contrived examples, but let’s think about some more real life examples. If we had to write our reduce() method similar to one that works on arrays , we again can’t define it as a lambda, because it needs to infer this from the invocation context, i.e., the array on which it was invoked.
For this reason, constructor functions can never be defined as arrow functions, as this for a constructor function can not be set at the time of its declaration. Every time a constructor function is invoked with the new keyword, a new object is created which then gets bound to that particular invocation.
Also when when frameworks or systems accept a callback function(s) to be invoked later with dynamic context this , we can’t use arrow functions as again this may need to change with every invocation. This situation commonly arises with DOM event handlers.
'use strict'
var button = document.getElementById('button');
button.addEventListener('click', function {
// web-api invokes with this bound to current-target in DOM
this.classList.toggle('on');
});
var button = document.getElementById('button');
button.addEventListener('click', () => {
// TypeError; 'use strict' -> no global this
this.classList.toggle('on');
});
This is also the reason why in frameworks like Angular 2+ and Vue.js expect the template-component binding methods to be regular function / methods as this for their invocation is managed by the frameworks for the binding functions. (Angular uses Zone.js to manage an async context for invocations of view-template binding functions.)
On the other hand, in React, when we want pass a component's method as an event-handler, for example, <input onChange={this.handleOnchange} />, we should define handleOnchanage = (event)=> {this.props.onInputChange(event.target.value);} as an arrow function as for every invocation. We want this to be the same instance of the component that produced the JSX for the rendered DOM element.
This article is also available in my Medium publication. If you like the article, or have any comments and suggestions, please clap or leave comments on Medium.
In a simple way,
var a = 20; function a() {this.a = 10; console.log(a);}
//20, since the context here is window.
Another instance:
var a = 20;
function ex(){
this.a = 10;
function inner(){
console.log(this.a); // Can you guess the output of this line?
}
inner();
}
var test = new ex();
Ans: The console would print 20.
The reason being whenever a function is executed its own stack is created, in this example the ex function is executed with the new operator so a context will be created, and when inner is executed it JavaScript would create a new stack and execute the inner function in a global context though there is a local context.
So, if we want the inner function to have a local context, which is ex, then we need to bind the context to the inner function.
Arrows solve this problem. Instead of taking the Global context, they take the local context if any exist. In the *given example, it will take new ex() as this.
So, in all cases where binding is explicit, arrows solve the problem by defaults.

Difference between req.param = function(){} and req.param = function param() {} [duplicate]

We have two different way for doing function expression in JavaScript:
Named function expression (NFE):
var boo = function boo () {
alert(1);
};
Anonymous function expression:
var boo = function () {
alert(1);
};
And both of them can be called with boo();. I really can't see why/when I should use anonymous functions and when I should use Named Function Expressions. What difference is there between them?
In the case of the anonymous function expression, the function is anonymous — literally, it has no name. The variable you're assigning it to has a name, but the function does not. (Update: That was true through ES5. As of ES2015 [aka ES6], often a function created with an anonymous expression gets a true name [but not an automatic identifier], read on...)
Names are useful. Names can be seen in stack traces, call stacks, lists of breakpoints, etc. Names are a Good Thing™.
(You used to have to beware of named function expressions in older versions of IE [IE8 and below], because they mistakenly created two completely separate function objects at two completely different times [more in my blog article Double take]. If you need to support IE8 [!!], it's probably best to stick with anonymous function expressions or function declarations, but avoid named function expressions.)
One key thing about a named function expression is that it creates an in-scope identifier with that name for the function within the functon body:
var x = function example() {
console.log(typeof example); // "function"
};
x();
console.log(typeof example); // "undefined"
As of ES2015, though, a lot of "anonymous" function expressions create functions with names, and this was predated by various modern JavaScript engines being quite smart about inferring names from context. In ES2015, your anonymous function expression results in a function with the name boo. However, even with ES2015+ semantics, the automatic identifier is not created:
var obj = {
x: function() {
console.log(typeof x); // "undefined"
console.log(obj.x.name); // "x"
},
y: function y() {
console.log(typeof y); // "function"
console.log(obj.y.name); // "y"
}
};
obj.x();
obj.y();
The assignment fo the function's name is done with the SetFunctionName abstract operation used in various operations in the spec.
The short version is basically any time an anonymous function expression appears on the right-hand side of something like an assignment or initialization, like:
var boo = function() { /*...*/ };
(or it could be let or const rather than var), or
var obj = {
boo: function() { /*...*/ }
};
or
doSomething({
boo: function() { /*...*/ }
});
(those last two are really the same thing), the resulting function will have a name (boo, in the examples).
There's an important, and intentional, exception: Assigning to a property on an existing object:
obj.boo = function() { /*...*/ }; // <== Does not get a name
This was because of information leak concerns raised when the new feature was going through the process of being added; details in my answer to another question here.
Naming functions is useful if they need to reference themselves (e.g. for recursive calls). Indeed, if you are passing a literal function expression as an argument directly to another function, that function expression cannot directly reference itself in ES5 strict mode unless it is named.
For example, consider this code:
setTimeout(function sayMoo() {
alert('MOO');
setTimeout(sayMoo, 1000);
}, 1000);
It would be impossible to write this code quite this cleanly if the function expression passed to setTimeout were anonymous; we would need to assign it to a variable instead prior to the setTimeout call. This way, with a named function expression, is slightly shorter and neater.
It was historically possible to write code like this even using an anonymous function expression, by exploiting arguments.callee...
setTimeout(function () {
alert('MOO');
setTimeout(arguments.callee, 1000);
}, 1000);
... but arguments.callee is deprecated, and is outright forbidden in ES5 strict mode. Hence MDN advises:
Avoid using arguments.callee() by either giving function expressions a name or use a function declaration where a function must call itself.
(emphasis mine)
You should always use named function expressions, that's why:
You can use the name of that function when you need recursion.
Anonymous functions doesn't help when debugging as you can't see the name of the function that causes problems.
When you do not name a function, later on its harder to understand what it's doing. Giving it a name makes it easier to understand.
var foo = function bar() {
//some code...
};
foo();
bar(); // Error!
Here, for example, because the name bar is used within a function expression, it doesn't get declared in the outer scope. With named function expressions, the name of the function expression is enclosed within its own scope.
If a function is specified as a Function Expression, it can be given a name.
It will only be available inside the function (except IE8-).
var f = function sayHi(name) {
alert( sayHi ); // Inside the function you can see the function code
};
alert( sayHi ); // (Error: undefined variable 'sayHi')
This name is intended for a reliable recursive function call, even if it is written to another variable.
In addition, the NFE (Named Function Expression) name CAN be overwritten with the Object.defineProperty(...) method as follows:
var test = function sayHi(name) {
Object.defineProperty(test, 'name', { value: 'foo', configurable: true });
alert( test.name ); // foo
};
test();
Note: that with the Function Declaration this can not be done. This "special" internal function name is specified only in the Function Expression syntax.
Using named function expressions is better, when you want to be able to reference the function in question without having to rely on deprecated features such as arguments.callee.

Trouble accessing a global function from within Google Map Listener function in Ionic 3 [duplicate]

With () => {} and function () {} we are getting two very similar ways to write functions in ES6. In other languages lambda functions often distinguish themselves by being anonymous, but in ECMAScript any function can be anonymous. Each of the two types have unique usage domains (namely when this needs to either be bound explicitly or explicitly not be bound). Between those domains there are a vast number of cases where either notation will do.
Arrow functions in ES6 have at least two limitations:
Don't work with new and cannot be used when creating prototype
Fixed this bound to scope at initialisation
These two limitations aside, arrow functions could theoretically replace regular functions almost anywhere. What is the right approach using them in practice? Should arrow functions be used e.g.:
"everywhere they work", i.e. everywhere a function does not have to be agnostic about the this variable and we are not creating an object.
only "everywhere they are needed", i.e. event listeners, timeouts, that need to be bound to a certain scope
with 'short' functions, but not with 'long' functions
only with functions that do not contain another arrow function
I am looking for a guideline to selecting the appropriate function notation in the future version of ECMAScript. The guideline will need to be clear, so that it can be taught to developers in a team, and to be consistent so that it does not require constant refactoring back and forth from one function notation to another.
The question is directed at people who have thought about code style in the context of the upcoming ECMAScript 6 (Harmony) and who have already worked with the language.
A while ago our team migrated all its code (a mid-sized AngularJS app) to JavaScript compiled using Traceur Babel. I'm now using the following rule of thumb for functions in ES6 and beyond:
Use function in the global scope and for Object.prototype properties.
Use class for object constructors.
Use => everywhere else.
Why use arrow functions almost everywhere?
Scope safety: When arrow functions are used consistently, everything is guaranteed to use the same thisObject as the root. If even a single standard function callback is mixed in with a bunch of arrow functions there's a chance the scope will become messed up.
Compactness: Arrow functions are easier to read and write. (This may seem opinionated so I will give a few examples further on.)
Clarity: When almost everything is an arrow function, any regular function immediately sticks out for defining the scope. A developer can always look up the next-higher function statement to see what the thisObject is.
Why always use regular functions on the global scope or module scope?
To indicate a function that should not access the thisObject.
The window object (global scope) is best addressed explicitly.
Many Object.prototype definitions live in the global scope (think String.prototype.truncate, etc.) and those generally have to be of type function anyway. Consistently using function on the global scope helps avoid errors.
Many functions in the global scope are object constructors for old-style class definitions.
Functions can be named1. This has two benefits: (1) It is less awkward to writefunction foo(){} than const foo = () => {} — in particular outside other function calls. (2) The function name shows in stack traces. While it would be tedious to name every internal callback, naming all the public functions is probably a good idea.
Function declarations are hoisted, (meaning they can be accessed before they are declared), which is a useful attribute in a static utility function.
Object constructors
Attempting to instantiate an arrow function throws an exception:
var x = () => {};
new x(); // TypeError: x is not a constructor
One key advantage of functions over arrow functions is therefore that functions double as object constructors:
function Person(name) {
this.name = name;
}
However, the functionally identical2 ECMAScript Harmony draft class definition is almost as compact:
class Person {
constructor(name) {
this.name = name;
}
}
I expect that use of the former notation will eventually be discouraged. The object constructor notation may still be used by some for simple anonymous object factories where objects are programmatically generated, but not for much else.
Where an object constructor is needed one should consider converting the function to a class as shown above. The syntax works with anonymous functions/classes as well.
Readability of arrow functions
The probably best argument for sticking to regular functions - scope safety be damned - would be that arrow functions are less readable than regular functions. If your code is not functional in the first place, then arrow functions may not seem necessary, and when arrow functions are not used consistently they look ugly.
ECMAScript has changed quite a bit since ECMAScript 5.1 gave us the functional Array.forEach, Array.map and all of these functional programming features that have us use functions where for loops would have been used before. Asynchronous JavaScript has taken off quite a bit. ES6 will also ship a Promise object, which means even more anonymous functions. There is no going back for functional programming. In functional JavaScript, arrow functions are preferable over regular functions.
Take for instance this (particularly confusing) piece of code3:
function CommentController(articles) {
this.comments = [];
articles.getList()
.then(articles => Promise.all(articles.map(article => article.comments.getList())))
.then(commentLists => commentLists.reduce((a, b) => a.concat(b)));
.then(comments => {
this.comments = comments;
})
}
The same piece of code with regular functions:
function CommentController(articles) {
this.comments = [];
articles.getList()
.then(function (articles) {
return Promise.all(articles.map(function (article) {
return article.comments.getList();
}));
})
.then(function (commentLists) {
return commentLists.reduce(function (a, b) {
return a.concat(b);
});
})
.then(function (comments) {
this.comments = comments;
}.bind(this));
}
While any one of the arrow functions can be replaced by a standard function, there would be very little to gain from doing so. Which version is more readable? I would say the first one.
I think the question whether to use arrow functions or regular functions will become less relevant over time. Most functions will either become class methods, which make away with the function keyword, or they will become classes. Functions will remain in use for patching classes through the Object.prototype. In the mean time I suggest reserving the function keyword for anything that should really be a class method or a class.
Notes
Named arrow functions have been deferred in the ES6 specification. They might still be added a future version.
According to the draft specification, "Class declarations/expressions create a constructor function/prototype pair exactly as for function declarations" as long as a class does not use the extend keyword. A minor difference is that class declarations are constants, whereas function declarations are not.
Note on blocks in single statement arrow functions: I like to use a block wherever an arrow function is called for the side effect alone (e.g., assignment). That way it is clear that the return value can be discarded.
According to the proposal, arrows aimed "to address and resolve several common pain points of traditional function expressions". They intended to improve matters by binding this lexically and offering terse syntax.
However,
One cannot consistently bind this lexically
Arrow function syntax is delicate and ambiguous
Therefore, arrow functions create opportunities for confusion and errors, and should be excluded from a JavaScript programmer's vocabulary, replaced with function exclusively.
Regarding lexical this
this is problematic:
function Book(settings) {
this.settings = settings;
this.pages = this.createPages();
}
Book.prototype.render = function () {
this.pages.forEach(function (page) {
page.draw(this.settings);
}, this);
};
Arrow functions intend to fix the problem where we need to access a property of this inside a callback. There are already several ways to do that: One could assign this to a variable, use bind, or use the third argument available on the Array aggregate methods. Yet arrows seem to be the simplest workaround, so the method could be refactored like this:
this.pages.forEach(page => page.draw(this.settings));
However, consider if the code used a library like jQuery, whose methods bind this specially. Now, there are two this values to deal with:
Book.prototype.render = function () {
var book = this;
this.$pages.each(function (index) {
var $page = $(this);
book.draw(book.currentPage + index, $page);
});
};
We must use function in order for each to bind this dynamically. We can't use an arrow function here.
Dealing with multiple this values can also be confusing, because it's hard to know which this an author was talking about:
function Reader() {
this.book.on('change', function () {
this.reformat();
});
}
Did the author actually intend to call Book.prototype.reformat? Or did he forget to bind this, and intend to call Reader.prototype.reformat? If we change the handler to an arrow function, we will similarly wonder if the author wanted the dynamic this, yet chose an arrow because it fit on one line:
function Reader() {
this.book.on('change', () => this.reformat());
}
One may pose: "Is it exceptional that arrows could sometimes be the wrong function to use? Perhaps if we only rarely need dynamic this values, then it would still be okay to use arrows most of the time."
But ask yourself this: "Would it be 'worth it' to debug code and find that the result of an error was brought upon by an 'edge case?'" I'd prefer to avoid trouble not just most of the time, but 100% of the time.
There is a better way: Always use function (so this can always be dynamically bound), and always reference this via a variable. Variables are lexical and assume many names. Assigning this to a variable will make your intentions clear:
function Reader() {
var reader = this;
reader.book.on('change', function () {
var book = this;
book.reformat();
reader.reformat();
});
}
Furthermore, always assigning this to a variable (even when there is a single this or no other functions) ensures one's intentions remain clear even after the code is changed.
Also, dynamic this is hardly exceptional. jQuery is used on over 50 million websites (as of this writing in February 2016). Here are other APIs binding this dynamically:
Mocha (~120k downloads yesterday) exposes methods for its tests via this.
Grunt (~63k downloads yesterday) exposes methods for build tasks via this.
Backbone (~22k downloads yesterday) defines methods accessing this.
Event APIs (like the DOM's) refer to an EventTarget with this.
Prototypal APIs that are patched or extended refer to instances with this.
(Statistics via http://trends.builtwith.com/javascript/jQuery and https://www.npmjs.com.)
You are likely to require dynamic this bindings already.
A lexical this is sometimes expected, but sometimes not; just as a dynamic this is sometimes expected, but sometimes not. Thankfully, there is a better way, which always produces and communicates the expected binding.
Regarding terse syntax
Arrow functions succeeded in providing a "shorter syntactical form" for functions. But will these shorter functions make you more successful?
Is x => x * x "easier to read" than function (x) { return x * x; }? Maybe it is, because it's more likely to produce a single, short line of code. According to Dyson's The influence of reading speed and line length on the effectiveness of reading from screen,
A medium line length (55 characters per line) appears to support effective reading at normal and fast speeds. This produced the highest level of comprehension . . .
Similar justifications are made for the conditional (ternary) operator, and for single-line if statements.
However, are you really writing the simple mathematical functions advertised in the proposal? My domains are not mathematical, so my subroutines are rarely so elegant. Rather, I commonly see arrow functions break a column limit, and wrap to another line due to the editor or style guide, which nullifies "readability" by Dyson's definition.
One might pose, "How about just using the short version for short functions, when possible?". But now a stylistic rule contradicts a language constraint: "Try to use the shortest function notation possible, keeping in mind that sometimes only the longest notation will bind this as expected." Such conflation makes arrows particularly prone to misuse.
There are numerous issues with arrow function syntax:
const a = x =>
doSomething(x);
const b = x =>
doSomething(x);
doSomethingElse(x);
Both of these functions are syntactically valid. But doSomethingElse(x); is not in the body of b. It is just a poorly-indented, top-level statement.
When expanding to the block form, there is no longer an implicit return, which one could forget to restore. But the expression may only have been intended to produce a side-effect, so who knows if an explicit return will be necessary going forward?
const create = () => User.create();
const create = () => {
let user;
User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
const create = () => {
let user;
return User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
What may be intended as a rest parameter can be parsed as the spread operator:
processData(data, ...results => {}) // Spread
processData(data, (...results) => {}) // Rest
Assignment can be confused with default arguments:
const a = 1;
let x;
const b = x => {}; // No default
const b = x = a => {}; // "Adding a default" instead creates a double assignment
const b = (x = a) => {}; // Remember to add parentheses
Blocks look like objects:
(id) => id // Returns `id`
(id) => {name: id} // Returns `undefined` (it's a labeled statement)
(id) => ({name: id}) // Returns an object
What does this mean?
() => {}
Did the author intend to create a no-op, or a function that returns an empty object? (With this in mind, should we ever place { after =>? Should we restrict ourselves to the expression syntax only? That would further reduce arrows' frequency.)
=> looks like <= and >=:
x => 1 ? 2 : 3
x <= 1 ? 2 : 3
if (x => 1) {}
if (x >= 1) {}
To invoke an arrow function expression immediately, one must place () on the outside, yet placing () on the inside is valid and could be intentional.
(() => doSomething()()) // Creates function calling value of `doSomething()`
(() => doSomething())() // Calls the arrow function
Although, if one writes (() => doSomething()()); with the intention of writing an immediately-invoked function expression, simply nothing will happen.
It's hard to argue that arrow functions are "more understandable" with all the above cases in mind. One could learn all the special rules required to utilize this syntax. Is it really worth it?
The syntax of function is unexceptionally generalized. To use function exclusively means the language itself prevents one from writing confusing code. To write procedures that should be syntactically understood in all cases, I choose function.
Regarding a guideline
You request a guideline that needs to be "clear" and "consistent." Using arrow functions will eventually result in syntactically-valid, logically-invalid code, with both function forms intertwined, meaningfully and arbitrarily. Therefore, I offer the following:
Guideline for Function Notation in ES6:
Always create procedures with function.
Always assign this to a variable. Do not use () => {}.
Arrow functions were created to simplify function scope and solving the this keyword by making it simpler. They utilize the => syntax, which looks like an arrow.
Note: It does not replace the existing functions. If you replace every function syntax with arrow functions, it's not going to work in all cases.
Let's have a look at the existing ES5 syntax. If the this keyword were inside an object’s method (a function that belongs to an object), what would it refer to?
var Actor = {
name: 'RajiniKanth',
getName: function() {
console.log(this.name);
}
};
Actor.getName();
The above snippet would refer to an object and print out the name "RajiniKanth". Let's explore the below snippet and see what would this point out here.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Now what about if the this keyword were inside of method’s function?
Here this would refer to window object than the inner function as its fallen out of scope. Because this, always references the owner of the function it is in, for this case — since it is now out of scope — the window/global object.
When it is inside of an object’s method — the function’s owner is the object. Thus the this keyword is bound to the object. Yet, when it is inside of a function, either stand alone or within another method, it will always refer to the window/global object.
var fn = function(){
alert(this);
}
fn(); // [object Window]
There are ways to solve this problem in our ES5 itself. Let us look into that before diving into ES6 arrow functions on how solve it.
Typically you would, create a variable outside of the method’s inner function. Now the ‘forEach’ method gains access to this and thus the object’s properties and their values.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
var _this = this;
this.movies.forEach(function(movie) {
alert(_this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Using bind to attach the this keyword that refers to the method to the method’s inner function.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
}.bind(this));
}
};
Actor.showMovies();
Now with the ES6 arrow function, we can deal with lexical scoping issue in a simpler way.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach((movie) => {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Arrow functions are more like function statements, except that they bind the this to the parent scope. If the arrow function is in the top scope, the this argument will refer to the window/global scope, while an arrow function inside a regular function will have its this argument the same as its outer function.
With arrow functions this is bound to the enclosing scope at creation time and cannot be changed. The new operator, bind, call, and apply have no effect on this.
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
// With a traditional function if we don't control
// the context then can we lose control of `this`.
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`
asyncFunction(o, function (param) {
// We made a mistake of thinking `this` is
// the instance of `o`.
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? false
In the above example, we lost the control of this. We can solve the above example by using a variable reference of this or using bind. With ES6, it becomes easier in managing the this as its bound to lexical scoping.
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`.
//
// Because this arrow function is created within
// the scope of `doSomething` it is bound to this
// lexical scope.
asyncFunction(o, (param) => {
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? true
When not to use arrow functions
Inside an object literal.
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
getName: () => {
alert(this.name);
}
};
Actor.getName();
Actor.getName is defined with an arrow function, but on invocation it alerts undefined because this.name is undefined as the context remains to window.
It happens because the arrow function binds the context lexically with the window object... i.e., the outer scope. Executing this.name is equivalent to window.name, which is undefined.
Object prototype
The same rule applies when defining methods on a prototype object. Instead of using an arrow function for defining sayCatName method, which brings an incorrect context window:
function Actor(name) {
this.name = name;
}
Actor.prototype.getName = () => {
console.log(this === window); // => true
return this.name;
};
var act = new Actor('RajiniKanth');
act.getName(); // => undefined
Invoking constructors
this in a construction invocation is the newly created object. When executing new Fn(), the context of the constructor Fn is a new object: this instanceof Fn === true.
this is setup from the enclosing context, i.e., the outer scope which makes it not assigned to newly created object.
var Message = (text) => {
this.text = text;
};
// Throws "TypeError: Message is not a constructor"
var helloMessage = new Message('Hello World!');
Callback with dynamic context
Arrow function binds the context statically on declaration and is not possible to make it dynamic. Attaching event listeners to DOM elements is a common task in client side programming. An event triggers the handler function with this as the target element.
var button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
});
this is window in an arrow function that is defined in the global context. When a click event happens, the browser tries to invoke the handler function with button context, but arrow function does not change its pre-defined context. this.innerHTML is equivalent to window.innerHTML and has no sense.
You have to apply a function expression, which allows to change this depending on the target element:
var button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this === button); // => true
this.innerHTML = 'Clicked button';
});
When user clicks the button, this in the handler function is the button. Thus this.innerHTML = 'Clicked button' correctly modifies the button text to reflect the clicked status.
References
When 'Not' to Use Arrow Functions
Arrow functions - most widely used ES6 feature so far ...
Usage: All ES5 functions should be replaced with ES6 arrow functions except in following scenarios:
Arrow functions should not be used:
When we want function hoisting
as arrow functions are anonymous.
When we want to use this/arguments in a function
as arrow functions do not have this/arguments of their own, they depend upon their outer context.
When we want to use named function
as arrow functions are anonymous.
When we want to use function as a constructor
as arrow functions do not have their own this.
When we want to add function as a property in object literal and use object in it
as we can not access this (which should be object itself).
Let us understand some of the variants of arrow functions to understand better:
Variant 1: When we want to pass more than one argument to a function and return some value from it.
ES5 version:
var multiply = function (a, b) {
return a*b;
};
console.log(multiply(5, 6)); // 30
ES6 version:
var multiplyArrow = (a, b) => a*b;
console.log(multiplyArrow(5, 6)); // 30
Note:
The function keyword is not required.
=> is required.
{} are optional, when we do not provide {} return is implicitly added by JavaScript and when we do provide {} we need to add return if we need it.
Variant 2: When we want to pass only one argument to a function and return some value from it.
ES5 version:
var double = function(a) {
return a*2;
};
console.log(double(2)); // 4
ES6 version:
var doubleArrow = a => a*2;
console.log(doubleArrow(2)); // 4
Note:
When passing only one argument we can omit the parentheses, ().
Variant 3: When we do not want to pass any argument to a function and do not want to return any value.
ES5 version:
var sayHello = function() {
console.log("Hello");
};
sayHello(); // Hello
ES6 version:
var sayHelloArrow = () => {console.log("sayHelloArrow");}
sayHelloArrow(); // sayHelloArrow
Variant 4: When we want to explicitly return from arrow functions.
ES6 version:
var increment = x => {
return x + 1;
};
console.log(increment(1)); // 2
Variant 5: When we want to return an object from arrow functions.
ES6 version:
var returnObject = () => ({a:5});
console.log(returnObject());
Note:
We need to wrap the object in parentheses, (). Otherwise, JavaScript cannot differentiate between a block and an object.
Variant 6: Arrow functions do not have arguments (an array like object) of their own. They depend upon outer context for arguments.
ES6 version:
function foo() {
var abc = i => arguments[0];
console.log(abc(1));
};
foo(2); // 2
Note:
foo is an ES5 function, with an arguments array like object and an argument passed to it is 2 so arguments[0] for foo is 2.
abc is an ES6 arrow function since it does not have its own arguments. Hence it prints arguments[0] of foo its outer context instead.
Variant 7: Arrow functions do not have this of their own they depend upon outer context for this
ES5 version:
var obj5 = {
greet: "Hi, Welcome ",
greetUser : function(user) {
setTimeout(function(){
console.log(this.greet + ": " + user); // "this" here is undefined.
});
}
};
obj5.greetUser("Katty"); //undefined: Katty
Note:
The callback passed to setTimeout is an ES5 function and it has its own this which is undefined in a use-strict environment. Hence we get the output:
undefined: Katty
ES6 version:
var obj6 = {
greet: "Hi, Welcome ",
greetUser : function(user) {
setTimeout(() => console.log(this.greet + ": " + user));
// This here refers to outer context
}
};
obj6.greetUser("Katty"); // Hi, Welcome: Katty
Note:
The callback passed to setTimeout is an ES6 arrow function and it does not have its own this, so it takes it from its outer context that is greetUser which has this. That is obj6 and hence we get the output:
Hi, Welcome: Katty
Miscellaneous:
We cannot use new with arrow functions.
Arrow functions do not have prototype property.
We do not have binding of this when an arrow function is invoked through apply or call.
I still stand by everything I wrote in my first answer in this thread. However, my opinion on code style has developed since then, so I have a new answer to this question that builds on my last one.
Regarding lexical this
In my last answer, I deliberately eschewed an underlying belief I hold about this language, as it was not directly related to the argument I was making. Nonetheless, without this being explicitly stated, I can understand why many people simply balk at my recommendation to not use arrows, when they find arrows so useful.
My belief is this: we shouldn’t be using this in the first place. Therefore, if a person deliberately avoids using this in his code, then the “lexical this” feature of arrows is of little to no value. Also, under the premise that this is a bad thing, arrow’s treatment of this is less of a “good thing;” instead, it’s more of a form of damage control for another bad language feature.
I figure that this either does not occur to some people, but even to those to whom it does, they must invariably find themselves working within codebases where this appears a hundred times per file, and a little (or a lot) of damage control is all a reasonable person could hope for. So arrows can be good, in a way, when they make a bad situation better.
Even if it is easier to write code with this with arrows than without them, the rules for using arrows remain very complex (see: current thread). Thus, guidelines are neither “clear” nor “consistent,” as you’ve requested. Even if programmers know about arrows’ ambiguities, I think they shrug and accept them anyway, because the value of lexical this overshadows them.
All this is a preface to the following realization: if one does not use this, then the ambiguity about this that arrows normally cause becomes irrelevant. Arrows become more neutral in this context.
Regarding terse syntax
When I wrote my first answer, I was of the opinion that even slavish adherence to best practices was a worthwhile price to pay if it meant I could produce more perfect code. But I eventually came to realize that terseness can serve as a form of abstraction that can improve code quality, too — enough so to justify straying from best practices sometimes.
In other words: dammit, I want one-liner functions, too!
Regarding a guideline
With the possibility of this-neutral arrow functions, and terseness being worth pursuit, I offer the following more lenient guideline:
Guideline for Function Notation in ES6:
Don’t use this.
Use function declarations for functions you’d call by name (because they’re hoisted).
Use arrow functions for callbacks (because they tend to be terser).
In addition to the great answers so far, I'd like to present a very different reason why arrow functions are in a certain sense fundamentally better than "ordinary" JavaScript functions.
For the sake of discussion, let's temporarily assume we use a type checker like TypeScript or Facebook's "Flow". Consider the following toy module, which is valid ECMAScript 6 code plus Flow type annotations (I'll include the untyped code, which would realistically result from Babel, at the end of this answer, so it can actually be run):
export class C {
n : number;
f1: number => number;
f2: number => number;
constructor(){
this.n = 42;
this.f1 = (x:number) => x + this.n;
this.f2 = function (x:number) { return x + this.n;};
}
}
Now see what happens when we use the class C from a different module, like this:
let o = { f1: new C().f1, f2: new C().f2, n: "foo" };
let n1: number = o.f1(1); // n1 = 43
console.log(n1 === 43); // true
let n2: number = o.f2(1); // n2 = "1foo"
console.log(n2 === "1foo"); // true, not a string!
As you can see, the type checker failed here: f2 was supposed to return a number, but it returned a string!
Worse, it seems that no conceivable type checker can handle ordinary (non-arrow) JavaScript functions, because the "this" of f2 does not occur in the argument list of f2, so the required type for "this" could not possibly be added as an annotation to f2.
Does this problem also affect people who don't use type checkers? I think so, because even when we have no static types, we think as if they're there. ("The first parameters must be a number, the second one a string" etc.) A hidden "this"-argument which may or may not be used in the function's body makes our mental bookkeeping harder.
Here is the runnable untyped version, which would be produced by Babel:
class C {
constructor() {
this.n = 42;
this.f1 = x => x + this.n;
this.f2 = function (x) { return x + this.n; };
}
}
let o = { f1: new C().f1, f2: new C().f2, n: "foo" };
let n1 = o.f1(1); // n1 = 43
console.log(n1 === 43); // true
let n2 = o.f2(1); // n2 = "1foo"
console.log(n2 === "1foo"); // true, not a string!
I prefer to use arrow functions at all times where access to local this is not needed, because arrow functions do not bind their own this, arguments, super, or new.target.
Arrow functions or lambdas, were introduced in ES 6. Apart from its elegance in minimal syntax, the most notable functional difference is scoping of this inside an arrow function
In regular function expressions, the this keyword is bound to different values based on the context in which it is called.
In arrow functions, this is lexically bound, which means it closes over this from the scope in which the arrow function was defined (parent-scope), and does not change no matter where and how it is invoked / called.
Limitations of arrow functions as methods on an object
// this = global Window
let objA = {
id: 10,
name: "Simar",
print () { // same as print: function()
console.log(`[${this.id} -> ${this.name}]`);
}
}
objA.print(); // logs: [10 -> Simar]
objA = {
id: 10,
name: "Simar",
print: () => {
// Closes over this lexically (global Window)
console.log(`[${this.id} -> ${this.name}]`);
}
};
objA.print(); // logs: [undefined -> undefined]
In the case of objA.print() when print() method defined using regular function, it worked by resolving this properly to objA for method invocation, but failed when defined as an arrow=> function. It is because this in a regular function when invoked as a method on an object (objA), is the object itself.
However, in case of an arrow function, this gets lexically bound to the the this of the enclosing scope where it was defined (global / Window in our case) and stays it stays same during its invocation as a method on objA.
There are advantages of an arrow-functions over regular functions in method(s) of an object, but only when this is expected to be fixed and bound at the time of definition.
/* this = global | Window (enclosing scope) */
let objB = {
id: 20,
name: "Paul",
print () { // Same as print: function()
setTimeout( function() {
// Invoked async, not bound to objB
console.log(`[${this.id} -> ${this.name}]`);
}, 1)
}
};
objB.print(); // Logs: [undefined -> undefined]'
objB = {
id: 20,
name: "Paul",
print () { // Same as print: function()
setTimeout( () => {
// Closes over bind to this from objB.print()
console.log(`[${this.id} -> ${this.name}]`);
}, 1)
}
};
objB.print(); // Logs: [20 -> Paul]
In the case of objB.print() where the print() method is defined as function that invokes console.log([${this.id} -> {this.name}]) asynchronously as a call-back on setTimeout , this resolved correctly to objB when an arrow function was used as call-back, but failed when the call-back was defined as as regular function.
It is because the arrow => function, passed to setTimeout(()=>..), closed over this lexically from its parent, i.e., invocation of objB.print() which defined it. In other words, the arrow => function passed in to to setTimeout(()==>... bound to objB as its this because the invocation of objB.print() this was objB itself.
We could easily use Function.prototype.bind() to make the call-back defined as a regular function work, by binding it to the correct this.
const objB = {
id: 20,
name: "Singh",
print () { // The same as print: function()
setTimeout( (function() {
console.log(`[${this.id} -> ${this.name}]`);
}).bind(this), 1)
}
}
objB.print() // logs: [20 -> Singh]
However, arrow functions come in handy and are less error prone for the case of async call-backs where we know the this at the time of the functions definition to which it gets and should be bound.
Limitation of Arrow-Functions where this needs to change across invocations
Anytime, we need a function whose this can be changed at the time of invocation, we can’t use arrow functions.
/* this = global | Window (enclosing scope) */
function print() {
console.log(`[${this.id} -> {this.name}]`);
}
const obj1 = {
id: 10,
name: "Simar",
print // The same as print: print
};
obj.print(); // Logs: [10 -> Simar]
const obj2 = {
id: 20,
name: "Paul",
};
printObj2 = obj2.bind(obj2);
printObj2(); // Logs: [20 -> Paul]
print.call(obj2); // logs: [20 -> Paul]
None of the above will work with arrow function const print = () => { console.log([${this.id} -> {this.name}]);} as this can’t be changed and will stay bound to the this of the enclosing scope where it was defined (global / Window).
In all these examples, we invoked the same function with different objects (obj1 and obj2) one after the another, both of which were created after the print() function was declared.
These were contrived examples, but let’s think about some more real life examples. If we had to write our reduce() method similar to one that works on arrays , we again can’t define it as a lambda, because it needs to infer this from the invocation context, i.e., the array on which it was invoked.
For this reason, constructor functions can never be defined as arrow functions, as this for a constructor function can not be set at the time of its declaration. Every time a constructor function is invoked with the new keyword, a new object is created which then gets bound to that particular invocation.
Also when when frameworks or systems accept a callback function(s) to be invoked later with dynamic context this , we can’t use arrow functions as again this may need to change with every invocation. This situation commonly arises with DOM event handlers.
'use strict'
var button = document.getElementById('button');
button.addEventListener('click', function {
// web-api invokes with this bound to current-target in DOM
this.classList.toggle('on');
});
var button = document.getElementById('button');
button.addEventListener('click', () => {
// TypeError; 'use strict' -> no global this
this.classList.toggle('on');
});
This is also the reason why in frameworks like Angular 2+ and Vue.js expect the template-component binding methods to be regular function / methods as this for their invocation is managed by the frameworks for the binding functions. (Angular uses Zone.js to manage an async context for invocations of view-template binding functions.)
On the other hand, in React, when we want pass a component's method as an event-handler, for example, <input onChange={this.handleOnchange} />, we should define handleOnchanage = (event)=> {this.props.onInputChange(event.target.value);} as an arrow function as for every invocation. We want this to be the same instance of the component that produced the JSX for the rendered DOM element.
This article is also available in my Medium publication. If you like the article, or have any comments and suggestions, please clap or leave comments on Medium.
In a simple way,
var a = 20; function a() {this.a = 10; console.log(a);}
//20, since the context here is window.
Another instance:
var a = 20;
function ex(){
this.a = 10;
function inner(){
console.log(this.a); // Can you guess the output of this line?
}
inner();
}
var test = new ex();
Ans: The console would print 20.
The reason being whenever a function is executed its own stack is created, in this example the ex function is executed with the new operator so a context will be created, and when inner is executed it JavaScript would create a new stack and execute the inner function in a global context though there is a local context.
So, if we want the inner function to have a local context, which is ex, then we need to bind the context to the inner function.
Arrows solve this problem. Instead of taking the Global context, they take the local context if any exist. In the *given example, it will take new ex() as this.
So, in all cases where binding is explicit, arrows solve the problem by defaults.

Javascript this when invoking a constructor? [duplicate]

I just came across an interesting situation in JavaScript. I have a class with a method that defines several objects using object-literal notation. Inside those objects, the this pointer is being used. From the behavior of the program, I have deduced that the this pointer is referring to the class on which the method was invoked, and not the object being created by the literal.
This seems arbitrary, though it is the way I would expect it to work. Is this defined behavior? Is it cross-browser safe? Is there any reasoning underlying why it is the way it is beyond "the spec says so" (for instance, is it a consequence of some broader design decision/philosophy)? Pared-down code example:
// inside class definition, itself an object literal, we have this function:
onRender: function() {
this.menuItems = this.menuItems.concat([
{
text: 'Group by Module',
rptletdiv: this
},
{
text: 'Group by Status',
rptletdiv: this
}]);
// etc
}
Cannibalized from another post of mine, here's more than you ever wanted to know about this.
Before I start, here's the most important thing to keep in mind about Javascript, and to repeat to yourself when it doesn't make sense. Javascript does not have classes (ES6 class is syntactic sugar). If something looks like a class, it's a clever trick. Javascript has objects and functions. (that's not 100% accurate, functions are just objects, but it can sometimes be helpful to think of them as separate things)
The this variable is attached to functions. Whenever you invoke a function, this is given a certain value, depending on how you invoke the function. This is often called the invocation pattern.
There are four ways to invoke functions in javascript. You can invoke the function as a method, as a function, as a constructor, and with apply.
As a Method
A method is a function that's attached to an object
var foo = {};
foo.someMethod = function(){
alert(this);
}
When invoked as a method, this will be bound to the object the function/method is a part of. In this example, this will be bound to foo.
As A Function
If you have a stand alone function, the this variable will be bound to the "global" object, almost always the window object in the context of a browser.
var foo = function(){
alert(this);
}
foo();
This may be what's tripping you up, but don't feel bad. Many people consider this a bad design decision. Since a callback is invoked as a function and not as a method, that's why you're seeing what appears to be inconsistent behavior.
Many people get around the problem by doing something like, um, this
var foo = {};
foo.someMethod = function (){
var that=this;
function bar(){
alert(that);
}
}
You define a variable that which points to this. Closure (a topic all its own) keeps that around, so if you call bar as a callback, it still has a reference.
NOTE: In use strict mode if used as function, this is not bound to global. (It is undefined).
As a Constructor
You can also invoke a function as a constructor. Based on the naming convention you're using (TestObject) this also may be what you're doing and is what's tripping you up.
You invoke a function as a Constructor with the new keyword.
function Foo(){
this.confusing = 'hell yeah';
}
var myObject = new Foo();
When invoked as a constructor, a new Object will be created, and this will be bound to that object. Again, if you have inner functions and they're used as callbacks, you'll be invoking them as functions, and this will be bound to the global object. Use that var that = this trick/pattern.
Some people think the constructor/new keyword was a bone thrown to Java/traditional OOP programmers as a way to create something similar to classes.
With the Apply Method
Finally, every function has a method (yes, functions are objects in Javascript) named "apply". Apply lets you determine what the value of this will be, and also lets you pass in an array of arguments. Here's a useless example.
function foo(a,b){
alert(a);
alert(b);
alert(this);
}
var args = ['ah','be'];
foo.apply('omg',args);
Function calls
Functions are just a type of Object.
All Function objects have call and apply methods which execute the Function object they're called on.
When called, the first argument to these methods specifies the object which will be referenced by the this keyword during execution of the Function - if it's null or undefined, the global object, window, is used for this.
Thus, calling a Function...
whereAmI = "window";
function foo()
{
return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}
...with parentheses - foo() - is equivalent to foo.call(undefined) or foo.apply(undefined), which is effectively the same as foo.call(window) or foo.apply(window).
>>> foo()
"this is window with 0 arguments"
>>> foo.call()
"this is window with 0 arguments"
Additional arguments to call are passed as the arguments to the function call, whereas a single additional argument to apply can specify the arguments for the function call as an Array-like object.
Thus, foo(1, 2, 3) is equivalent to foo.call(null, 1, 2, 3) or foo.apply(null, [1, 2, 3]).
>>> foo(1, 2, 3)
"this is window with 3 arguments"
>>> foo.apply(null, [1, 2, 3])
"this is window with 3 arguments"
If a function is a property of an object...
var obj =
{
whereAmI: "obj",
foo: foo
};
...accessing a reference to the Function via the object and calling it with parentheses - obj.foo() - is equivalent to foo.call(obj) or foo.apply(obj).
However, functions held as properties of objects are not "bound" to those objects. As you can see in the definition of obj above, since Functions are just a type of Object, they can be referenced (and thus can be passed by reference to a Function call or returned by reference from a Function call). When a reference to a Function is passed, no additional information about where it was passed from is carried with it, which is why the following happens:
>>> baz = obj.foo;
>>> baz();
"this is window with 0 arguments"
The call to our Function reference, baz, doesn't provide any context for the call, so it's effectively the same as baz.call(undefined), so this ends up referencing window. If we want baz to know that it belongs to obj, we need to somehow provide that information when baz is called, which is where the first argument to call or apply and closures come into play.
Scope chains
function bind(func, context)
{
return function()
{
func.apply(context, arguments);
};
}
When a Function is executed, it creates a new scope and has a reference to any enclosing scope. When the anonymous function is created in the above example, it has a reference to the scope it was created in, which is bind's scope. This is known as a "closure."
[global scope (window)] - whereAmI, foo, obj, baz
|
[bind scope] - func, context
|
[anonymous scope]
When you attempt to access a variable this "scope chain" is walked to find a variable with the given name - if the current scope doesn't contain the variable, you look at the next scope in the chain, and so on until you reach the global scope. When the anonymous function is returned and bind finishes executing, the anonymous function still has a reference to bind's scope, so bind's scope doesn't "go away".
Given all the above you should now be able to understand how scope works in the following example, and why the technique for passing a function around "pre-bound" with a particular value of this it will have when it is called works:
>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"
Is this defined behavior? Is it
cross-browser safe?
Yes. And yes.
Is there any reasoning underlying why
it is the way it is...
The meaning of this is pretty simple to deduce:
If this is used inside a constructor function, and the function was invoked with the new keyword, this refers to the object that will be created. this will continue to mean the object even in public methods.
If this is used anywhere else, including nested protected functions, it refers to the global scope (which in the case of the browser is the window object).
The second case is obviously a design flaw, but it's pretty easy to work around it by using closures.
In this case the inner this is bound to the global object instead of to the this variable of the outer function.
It's the way the language is designed.
See "JavaScript: The Good Parts" by Douglas Crockford for a good explanation.
I found a nice tutorial about the ECMAScript this
A this value is a special object which is related with the execution
context. Therefore, it may be named as a context object (i.e. an
object in which context the execution context is activated).
Any object may be used as this value of the context.
a this value is a property of the execution context, but not a
property of the variable object.
This feature is very important, because in contrary to variables, this value never participates in identifier resolution process. I.e. when accessing this in a code, its value is taken directly from the execution context and without any scope chain lookup. The value of this is determinate only once when entering the context.
In the global context, a this value is the global object itself (that means, this value here equals to variable object)
In case of a function context, this value in every single function call may be different
Reference Javascript-the-core and Chapter-3-this
All the answers here are very helpful but I still had a hard time to figure out what this point to in my case, which involved object destructuring. So I would like to add one more answer using a simplified version of my code,
let testThis = {
x: 12,
y: 20,
add({ a, b, c }) {
let d = a + b + c()
console.log(d)
},
test() {
//the result is NaN
this.add({
a: this.x,
b: this.y,
c: () => {
//this here is testThis, NOT the object literal here
return this.a + this.b
},
})
},
test2() {
//64 as expected
this.add({
a: this.x,
b: this.y,
c: () => {
return this.x + this.y
},
})
},
test3() {
//NaN
this.add({
a: this.x,
b: this.y,
c: function () {
//this here is the global object
return this.x + this.y
},
})
},
}
As here explained Javascript - destructuring object - 'this' set to global or undefined, instead of object it actually has nothing to do with object destructuring but how c() is called, but it is not easy to see through it here.
MDN says "arrow function expressions are best suited for non-method functions" but arrow function works here.
this in JS:
There are 3 types of functions where this has a different meaning. They are best explained via example:
Constructor
// In a constructor function this refers to newly created object
// Every function can be a constructor function in JavaScript e.g.
function Dog(color){
this.color = color;
}
// constructor functions are invoked by putting new in front of the function call
const myDog = new Dog('red');
// logs Dog has color red
console.log('Dog has color ' + myDog.color);
Normal function or method
// Browswer example:
console.log(this === window) // true
function myFn(){
console.log(this === window)
}
myFn(); // logs true
// The value of this depends on the context object.
// In this case the context from where the function is called is global.
// For the global context in the browser the context object is window.
const myObj = {fn: myFn}
myObj.fn() // logs false
// In this case the context from where the function is called is myObj.
// Therefore, false is logged.
myObj.fn2 = function myFn(){
console.log(this === myObj)
}
myObj.fn2() // logs true
// In this case the context from where the function is called is myObj.
// Therefore, true is logged.
Event listener
Inside the function of an event handler this will refer to the DOM element which detected the event. See this question: Using this inside an event handler

What is the difference between named and anonymous functions in var declaration? [duplicate]

We have two different way for doing function expression in JavaScript:
Named function expression (NFE):
var boo = function boo () {
alert(1);
};
Anonymous function expression:
var boo = function () {
alert(1);
};
And both of them can be called with boo();. I really can't see why/when I should use anonymous functions and when I should use Named Function Expressions. What difference is there between them?
In the case of the anonymous function expression, the function is anonymous — literally, it has no name. The variable you're assigning it to has a name, but the function does not. (Update: That was true through ES5. As of ES2015 [aka ES6], often a function created with an anonymous expression gets a true name [but not an automatic identifier], read on...)
Names are useful. Names can be seen in stack traces, call stacks, lists of breakpoints, etc. Names are a Good Thing™.
(You used to have to beware of named function expressions in older versions of IE [IE8 and below], because they mistakenly created two completely separate function objects at two completely different times [more in my blog article Double take]. If you need to support IE8 [!!], it's probably best to stick with anonymous function expressions or function declarations, but avoid named function expressions.)
One key thing about a named function expression is that it creates an in-scope identifier with that name for the function within the functon body:
var x = function example() {
console.log(typeof example); // "function"
};
x();
console.log(typeof example); // "undefined"
As of ES2015, though, a lot of "anonymous" function expressions create functions with names, and this was predated by various modern JavaScript engines being quite smart about inferring names from context. In ES2015, your anonymous function expression results in a function with the name boo. However, even with ES2015+ semantics, the automatic identifier is not created:
var obj = {
x: function() {
console.log(typeof x); // "undefined"
console.log(obj.x.name); // "x"
},
y: function y() {
console.log(typeof y); // "function"
console.log(obj.y.name); // "y"
}
};
obj.x();
obj.y();
The assignment fo the function's name is done with the SetFunctionName abstract operation used in various operations in the spec.
The short version is basically any time an anonymous function expression appears on the right-hand side of something like an assignment or initialization, like:
var boo = function() { /*...*/ };
(or it could be let or const rather than var), or
var obj = {
boo: function() { /*...*/ }
};
or
doSomething({
boo: function() { /*...*/ }
});
(those last two are really the same thing), the resulting function will have a name (boo, in the examples).
There's an important, and intentional, exception: Assigning to a property on an existing object:
obj.boo = function() { /*...*/ }; // <== Does not get a name
This was because of information leak concerns raised when the new feature was going through the process of being added; details in my answer to another question here.
Naming functions is useful if they need to reference themselves (e.g. for recursive calls). Indeed, if you are passing a literal function expression as an argument directly to another function, that function expression cannot directly reference itself in ES5 strict mode unless it is named.
For example, consider this code:
setTimeout(function sayMoo() {
alert('MOO');
setTimeout(sayMoo, 1000);
}, 1000);
It would be impossible to write this code quite this cleanly if the function expression passed to setTimeout were anonymous; we would need to assign it to a variable instead prior to the setTimeout call. This way, with a named function expression, is slightly shorter and neater.
It was historically possible to write code like this even using an anonymous function expression, by exploiting arguments.callee...
setTimeout(function () {
alert('MOO');
setTimeout(arguments.callee, 1000);
}, 1000);
... but arguments.callee is deprecated, and is outright forbidden in ES5 strict mode. Hence MDN advises:
Avoid using arguments.callee() by either giving function expressions a name or use a function declaration where a function must call itself.
(emphasis mine)
You should always use named function expressions, that's why:
You can use the name of that function when you need recursion.
Anonymous functions doesn't help when debugging as you can't see the name of the function that causes problems.
When you do not name a function, later on its harder to understand what it's doing. Giving it a name makes it easier to understand.
var foo = function bar() {
//some code...
};
foo();
bar(); // Error!
Here, for example, because the name bar is used within a function expression, it doesn't get declared in the outer scope. With named function expressions, the name of the function expression is enclosed within its own scope.
If a function is specified as a Function Expression, it can be given a name.
It will only be available inside the function (except IE8-).
var f = function sayHi(name) {
alert( sayHi ); // Inside the function you can see the function code
};
alert( sayHi ); // (Error: undefined variable 'sayHi')
This name is intended for a reliable recursive function call, even if it is written to another variable.
In addition, the NFE (Named Function Expression) name CAN be overwritten with the Object.defineProperty(...) method as follows:
var test = function sayHi(name) {
Object.defineProperty(test, 'name', { value: 'foo', configurable: true });
alert( test.name ); // foo
};
test();
Note: that with the Function Declaration this can not be done. This "special" internal function name is specified only in the Function Expression syntax.
Using named function expressions is better, when you want to be able to reference the function in question without having to rely on deprecated features such as arguments.callee.

Categories