bind() with arrow functions? [duplicate] - javascript

I've read in several places that the key difference is that this is lexically bound in arrow functions. That's all well and good, but I don't actually know what that means.
I know it means it's unique within the confines of the braces defining the function's body, but I couldn't actually tell you the output of the following code, because I have no idea what this is referring to, unless it's referring to the fat arrow function itself....which doesn't seem useful.
var testFunction = () => {
console.log(this)
};
testFunction();

Arrow functions capture the this value of the enclosing context
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}
var p = new Person();
So, to directly answer your question, this inside your arrow function would have the same value as it did right before the arrow function was assigned.

In order to provide the big picture I'm going to explain both, dynamic and lexical binding.
Dynamic Name Binding
this refers to the object the method is called on. This is a regularly to be read sentence on SO. But it is still only a phrase, pretty abstract. Is there a corresponding code pattern to this sentence?
Yes there is:
const o = {
m() { console.log(this) }
}
// the important patterns: applying methods
o.m(); // logs o
o["m"](); // logs o
m is a method because it relies on this. o.m() or o["m"]() means m is applied to o. These patterns are the Javascript translation to our famous phrase.
There is another important code pattern that you should pay attention to:
"use strict";
const o = {
m() { console.log(this) }
}
// m is passed to f as a callback
function f(m) { m() }
// another important pattern: passing methods
f(o.m); // logs undefined
f(o["m"]); // logs undefined
It is very similar to the previous pattern, only the parenthesis are missing. But the consequences are considerable: When you pass m to the function f, you pull outm of its object/context o. It is uprooted now and this refers to nothing (strict mode assumed).
Lexical (or Static) Name Binding
Arrow functions don't have their own this/super/arguments binding. They inherit them from their parent lexical scope:
const toString = Object.prototype.toString;
const o = {
foo: () => console.log("window", toString.call(this)),
bar() {
const baz = () => console.log("o", toString.call(this));
baz();
}
}
o.foo() // logs window [object Window]
o.bar() // logs o [object Object]
Apart from the global scope (Window in browsers) only functions are able to form a scope in Javascript (and {} blocks in ES2015). When the o.foo arrow function is called there is no surrounding function from which baz could inherit its this. Consequently it captures the this binding of the global scope which is bound to the Window object.
When baz is invoked by o.bar, the arrow function is surrounded by o.bar (o.bar forms its parent lexical scope) and can inherit o.bar's this binding. o.bar was called on o and thus its this is bound to o.

Hope this code show could give you clearer idea. Basically, 'this' in arrow function is the current context version of 'this'. See the code:
// 'this' in normal function & arrow function
var this1 = {
number: 123,
logFunction: function () { console.log(this); },
logArrow: () => console.log(this)
};
this1.logFunction(); // Object { number: 123}
this1.logArrow(); // Window

Arrow function this is pointing to the surrounding parent in Es6, means it doesn't scope like anonymous functions in ES5...
It's very useful way to avoid assigning var self to this which is widely used in ES5...
Look at the example below, assigning a function inside an object:
var checkThis = {
normalFunction: function () { console.log(this); },
arrowFunction: () => console.log(this)
};
checkThis.normalFunction(); //Object {}
checkThis.arrowFunction(); //Window {external: Object, chrome: Object, document: document, tmpDebug: "", j: 0…}

You can try to understand it by following the way below
// whatever here it is, function or fat arrow or literally object declare
// in short, a pair of curly braces should be appeared here, eg:
function f() {
// the 'this' here is the 'this' in fat arrow function below, they are
// bind together right here
// if 'this' is meaningful here, eg. this === awesomeObject is true
console.log(this) // [object awesomeObject]
let a = (...param) => {
// 'this is meaningful here too.
console.log(this) // [object awesomeObject]
}
so 'this' in fat arrow function is not bound, means you can not make anything bind to 'this' here, .apply won't, .call won't, .bind won't. 'this' in fat arrow function is bound when you write down the code text in your text editor. 'this' in fat arrow function is literally meaningful here. What your code write here in text editor is what your app run there in repl. What 'this' bound in fat arror will never change unless you change it in text editor.
Sorry for my pool English...

Arrow function never binds with this keyword
var env = "globalOutside";
var checkThis = {env: "insideNewObject", arrowFunc: () => {
console.log("environment: ", this.env);
} }
checkThis.arrowFunc() // expected answer is environment: globalOutside
// Now General function
var env = "globalOutside";
var checkThis = {env: "insideNewObject", generalFunc: function() {
console.log("environment: ", this.env);
} }
checkThis.generalFunc() // expected answer is enviroment: insideNewObject
// Hence proving that arrow function never binds with 'this'

this will always refer to the global object when used inside an arrow function. Use the regular function declaration to refer to the local object. Also, you can use the object name as the context (object.method, not this.method) for it to refer to the local object instead of the global(window).

In another example, if you click the age button below
<script>
var person = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: function() {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
var person2 = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: () => {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
</script>
<input type=button onClick="alert(person2.age());" value="Age">
it will throw an exception like this
×JavaScript error: Uncaught TypeError: Cannot read property
'getFullYear' of undefined on line 18
But if you change person2's this line
return new Date().getFullYear() - this.dob.getFullYear();
to
return new Date().getFullYear() - person2.dob.getFullYear();
it will work because this scope has changed in person2

Differences between arrow functions to regular functions: (taken from w3schools)
With arrow functions there are no binding of this.
In regular functions the this keyword represented the object that called the function, which could be the window, the document, a button or whatever.
With arrow functions the this keyword always represents the object that defined the arrow function.
// Regular Function:
hello = function() {
document.getElementById("demo").innerHTML += this;
}
// The window object calls the function:
window.addEventListener("load", hello);
// A button object calls the function:
document.getElementById("btn").addEventListener("click", hello);
// -------------------------------------------
// Arrow function
hello2 = () => {
document.getElementById("demo2").innerHTML += this;
}
// The window object calls the function:
window.addEventListener("load", hello2);
// A button object calls the function:
document.getElementById("btn2").addEventListener("click", hello2);
<p><i>With a regular function this represents the <b>object that calls the function</b>:</i></p>
<button id='btn'>click me regular function</button>
<p id="demo">Regular function: </p>
<hr>
<p><i>With arrow function this represents the <b>owner of the function(=the window object)</b>:</i></p>
<button id='btn2'>click me arrow function</button>
<p id="demo2">Arrow function: </p>

A related issue:
Came from - Why can't I access `this` within an arrow function?
We know below from here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Does not have its own bindings to this or super, and should not be used as methods.
Arrow functions establish "this" based on the scope the Arrow function is defined within.
Had a issue with this using arrow functions, so created a class (can be function), and class variable is accessed in arrow function, thereby achieved smaller functions using arrow functions without function keyword:
class MyClassOrFunction {
values = [];
size = () => this.values.length;
isEmpty = () => this.size() === 0;
}
let obj = new MyClassOrFunction();
obj.size(); // function call here
You can also have a getter like this, that does not have function keyword, but a bit longer due to return statement, also can access other member functions:
class MyClassOrFunction {
values = [];
size = () => this.values.length;
get length() { return this.size(); }
}
let obj = new MyClassOrFunction();
obj.length; // NOTE: no function call here

Related

Can someone explain to me why the keyword `this`, in these arrow functions, ends up with the given values in these examples

According to (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions):
An arrow function does not have its own this. The this value of the
enclosing lexical scope is used; arrow functions follow the normal
variable lookup rules.
Here's some examples of where what I thought was the arrow function's this is wrong. (I have not embedded runable code into the question because it gives me different results than my code-editor - Visual Studio Code that's running with node). Could someone explain my examples?
1.
f = param1 => console.log(this);
f(); //expected: global object prints: {}
2.
var bike = {
owner: 'Adam',
getOwner: () => {
console.log(this.owner);
}
};
bike.getOwner(); //expected: 'Adam' prints: undefined
An arrow function does not have its own this. The this value of the enclosing lexical scope is used; arrow functions follow the normal variable lookup rules.
So what you need to think of is, what would this refer to if it wasn't in it's own function?
So if we have an IIFE, like:
(() => console.log(this.foo))();
this is equivalent to
console.log(this.foo)
So, using your example:
var bike = {
owner: 'Adam',
getOwner: (() => {
console.log(this.owner);
})()
};
is equivalent to:
var bike = {
owner: 'Adam',
getOwner: console.log(this.owner)
};
and obviously, this.owner doesn't exist.
You could also think of an arrow function as a regular function where you .bind(this) to it:
this.tmp = 'a';
x = () => {
console.log(this.tmp);
}
y = function() {
console.log(this.tmp);
}.bind(this)
x();
y();
The problem is that you are not running the code in a browser (or Node). In both of your examples, this refers to the global object.
Probably wherever you're running the code doesn't provide the usual global object (faster? more secure?) and instead provides {}.
In your case, using traditional function keyword instead of lambda function solves the problem.
var bike = {
owner: 'Adam',
getOwner: function() {
console.log(this.owner);
}};
bike.getOwner();
well they are two cases for this keyword the global Object which is window in the browser or Global in Node JS and the second case is object if it called within any method of that object. so if you called function or run it in the global scope it will refer to the global object as I mentioned before either if it is an arrow function or ordinary function for example:
function foo () {
console.log(this);
}
let bar = () => console.log(this);
foo() // window
bar() // window
the second case it will refer to the object for example:
let obj = {
name: "john doe",
sayName(){
console.log(this.name);
}
}
obj.sayName() // john doe
I hope this will explain you what is the heck of this keyword
For arrow functions, do not require to bind. takes the reference of where the arrow function has defintion.
1 point - This will print the props where the arrow was defined
2 point - is compilation successful, because colon are not suppose to be with arrow function is this fashion.
How are you trying the execution of this code!

How does javascript fat arrow vs normal function set `this`? [duplicate]

I've read in several places that the key difference is that this is lexically bound in arrow functions. That's all well and good, but I don't actually know what that means.
I know it means it's unique within the confines of the braces defining the function's body, but I couldn't actually tell you the output of the following code, because I have no idea what this is referring to, unless it's referring to the fat arrow function itself....which doesn't seem useful.
var testFunction = () => {
console.log(this)
};
testFunction();
Arrow functions capture the this value of the enclosing context
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}
var p = new Person();
So, to directly answer your question, this inside your arrow function would have the same value as it did right before the arrow function was assigned.
In order to provide the big picture I'm going to explain both, dynamic and lexical binding.
Dynamic Name Binding
this refers to the object the method is called on. This is a regularly to be read sentence on SO. But it is still only a phrase, pretty abstract. Is there a corresponding code pattern to this sentence?
Yes there is:
const o = {
m() { console.log(this) }
}
// the important patterns: applying methods
o.m(); // logs o
o["m"](); // logs o
m is a method because it relies on this. o.m() or o["m"]() means m is applied to o. These patterns are the Javascript translation to our famous phrase.
There is another important code pattern that you should pay attention to:
"use strict";
const o = {
m() { console.log(this) }
}
// m is passed to f as a callback
function f(m) { m() }
// another important pattern: passing methods
f(o.m); // logs undefined
f(o["m"]); // logs undefined
It is very similar to the previous pattern, only the parenthesis are missing. But the consequences are considerable: When you pass m to the function f, you pull outm of its object/context o. It is uprooted now and this refers to nothing (strict mode assumed).
Lexical (or Static) Name Binding
Arrow functions don't have their own this/super/arguments binding. They inherit them from their parent lexical scope:
const toString = Object.prototype.toString;
const o = {
foo: () => console.log("window", toString.call(this)),
bar() {
const baz = () => console.log("o", toString.call(this));
baz();
}
}
o.foo() // logs window [object Window]
o.bar() // logs o [object Object]
Apart from the global scope (Window in browsers) only functions are able to form a scope in Javascript (and {} blocks in ES2015). When the o.foo arrow function is called there is no surrounding function from which baz could inherit its this. Consequently it captures the this binding of the global scope which is bound to the Window object.
When baz is invoked by o.bar, the arrow function is surrounded by o.bar (o.bar forms its parent lexical scope) and can inherit o.bar's this binding. o.bar was called on o and thus its this is bound to o.
Hope this code show could give you clearer idea. Basically, 'this' in arrow function is the current context version of 'this'. See the code:
// 'this' in normal function & arrow function
var this1 = {
number: 123,
logFunction: function () { console.log(this); },
logArrow: () => console.log(this)
};
this1.logFunction(); // Object { number: 123}
this1.logArrow(); // Window
Arrow function this is pointing to the surrounding parent in Es6, means it doesn't scope like anonymous functions in ES5...
It's very useful way to avoid assigning var self to this which is widely used in ES5...
Look at the example below, assigning a function inside an object:
var checkThis = {
normalFunction: function () { console.log(this); },
arrowFunction: () => console.log(this)
};
checkThis.normalFunction(); //Object {}
checkThis.arrowFunction(); //Window {external: Object, chrome: Object, document: document, tmpDebug: "", j: 0…}
You can try to understand it by following the way below
// whatever here it is, function or fat arrow or literally object declare
// in short, a pair of curly braces should be appeared here, eg:
function f() {
// the 'this' here is the 'this' in fat arrow function below, they are
// bind together right here
// if 'this' is meaningful here, eg. this === awesomeObject is true
console.log(this) // [object awesomeObject]
let a = (...param) => {
// 'this is meaningful here too.
console.log(this) // [object awesomeObject]
}
so 'this' in fat arrow function is not bound, means you can not make anything bind to 'this' here, .apply won't, .call won't, .bind won't. 'this' in fat arrow function is bound when you write down the code text in your text editor. 'this' in fat arrow function is literally meaningful here. What your code write here in text editor is what your app run there in repl. What 'this' bound in fat arror will never change unless you change it in text editor.
Sorry for my pool English...
Arrow function never binds with this keyword
var env = "globalOutside";
var checkThis = {env: "insideNewObject", arrowFunc: () => {
console.log("environment: ", this.env);
} }
checkThis.arrowFunc() // expected answer is environment: globalOutside
// Now General function
var env = "globalOutside";
var checkThis = {env: "insideNewObject", generalFunc: function() {
console.log("environment: ", this.env);
} }
checkThis.generalFunc() // expected answer is enviroment: insideNewObject
// Hence proving that arrow function never binds with 'this'
this will always refer to the global object when used inside an arrow function. Use the regular function declaration to refer to the local object. Also, you can use the object name as the context (object.method, not this.method) for it to refer to the local object instead of the global(window).
In another example, if you click the age button below
<script>
var person = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: function() {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
var person2 = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: () => {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
</script>
<input type=button onClick="alert(person2.age());" value="Age">
it will throw an exception like this
×JavaScript error: Uncaught TypeError: Cannot read property
'getFullYear' of undefined on line 18
But if you change person2's this line
return new Date().getFullYear() - this.dob.getFullYear();
to
return new Date().getFullYear() - person2.dob.getFullYear();
it will work because this scope has changed in person2
Differences between arrow functions to regular functions: (taken from w3schools)
With arrow functions there are no binding of this.
In regular functions the this keyword represented the object that called the function, which could be the window, the document, a button or whatever.
With arrow functions the this keyword always represents the object that defined the arrow function.
// Regular Function:
hello = function() {
document.getElementById("demo").innerHTML += this;
}
// The window object calls the function:
window.addEventListener("load", hello);
// A button object calls the function:
document.getElementById("btn").addEventListener("click", hello);
// -------------------------------------------
// Arrow function
hello2 = () => {
document.getElementById("demo2").innerHTML += this;
}
// The window object calls the function:
window.addEventListener("load", hello2);
// A button object calls the function:
document.getElementById("btn2").addEventListener("click", hello2);
<p><i>With a regular function this represents the <b>object that calls the function</b>:</i></p>
<button id='btn'>click me regular function</button>
<p id="demo">Regular function: </p>
<hr>
<p><i>With arrow function this represents the <b>owner of the function(=the window object)</b>:</i></p>
<button id='btn2'>click me arrow function</button>
<p id="demo2">Arrow function: </p>
A related issue:
Came from - Why can't I access `this` within an arrow function?
We know below from here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Does not have its own bindings to this or super, and should not be used as methods.
Arrow functions establish "this" based on the scope the Arrow function is defined within.
Had a issue with this using arrow functions, so created a class (can be function), and class variable is accessed in arrow function, thereby achieved smaller functions using arrow functions without function keyword:
class MyClassOrFunction {
values = [];
size = () => this.values.length;
isEmpty = () => this.size() === 0;
}
let obj = new MyClassOrFunction();
obj.size(); // function call here
You can also have a getter like this, that does not have function keyword, but a bit longer due to return statement, also can access other member functions:
class MyClassOrFunction {
values = [];
size = () => this.values.length;
get length() { return this.size(); }
}
let obj = new MyClassOrFunction();
obj.length; // NOTE: no function call here

What is 'this' inside the scope of the promise then() or catch()? [duplicate]

I know that the >= operator means more than or equal to, but I've seen => in some source code. What's the meaning of that operator?
Here's the code:
promiseTargetFile(fpParams, aSkipPrompt, relatedURI).then(aDialogAccepted => {
if (!aDialogAccepted)
return;
saveAsType = fpParams.saveAsType;
file = fpParams.file;
continueSave();
}).then(null, Components.utils.reportError);
What It Is
This is an arrow function. Arrow functions are a short syntax, introduced by ECMAscript 6, that can be used similarly to the way you would use function expressions. In other words, you can often use them in place of expressions like function (foo) {...}. But they have some important differences. For example, they do not bind their own values of this (see below for discussion).
Arrow functions are part of the ECMAscript 6 specification. They are not yet supported in all browsers, but they are partially or fully supported in Node v. 4.0+ and in most modern browsers in use as of 2018. (I’ve included a partial list of supporting browsers below).
You can read more in the Mozilla documentation on arrow functions.
From the Mozilla documentation:
An arrow function expression (also known as fat arrow function) has a shorter syntax compared to function expressions and lexically binds the this value (does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous. These function expressions are best suited for non-method functions and they can not be used as constructors.
A Note on How this Works in Arrow Functions
One of the most handy features of an arrow function is buried in the text above:
An arrow function... lexically binds the this value (does not bind its own this...)
What this means in simpler terms is that the arrow function retains the this value from its context and does not have its own this. A traditional function may bind its own this value, depending on how it is defined and called. This can require lots of gymnastics like self = this;, etc., to access or manipulate this from one function inside another function. For more info on this topic, see the explanation and examples in the Mozilla documentation.
Example Code
Example (also from the docs):
var a = [
"We're up all night 'til the sun",
"We're up all night to get some",
"We're up all night for good fun",
"We're up all night to get lucky"
];
// These two assignments are equivalent:
// Old-school:
var a2 = a.map(function(s){ return s.length });
// ECMAscript 6 using arrow functions
var a3 = a.map( s => s.length );
// both a2 and a3 will be equal to [31, 30, 31, 31]
Notes on Compatibility
You can use arrow functions in Node, but browser support is spotty.
Browser support for this functionality has improved quite a bit, but it still is not widespread enough for most browser-based usages. As of December 12, 2017, it is supported in current versions of:
Chrome (v. 45+)
Firefox (v. 22+)
Edge (v. 12+)
Opera (v. 32+)
Android Browser (v. 47+)
Opera Mobile (v. 33+)
Chrome for Android (v. 47+)
Firefox for Android (v. 44+)
Safari (v. 10+)
iOS Safari (v. 10.2+)
Samsung Internet (v. 5+)
Baidu Browser (v. 7.12+)
Not supported in:
IE (through v. 11)
Opera Mini (through v. 8.0)
Blackberry Browser (through v. 10)
IE Mobile (through v. 11)
UC Browser for Android (through v. 11.4)
QQ (through v. 1.2)
You can find more (and more current) information at CanIUse.com (no affiliation).
That's known as an Arrow Function, part of the ECMAScript 2015 spec...
var foo = ['a', 'ab', 'abc'];
var bar = foo.map(f => f.length);
console.log(bar); // 1,2,3
Shorter syntax than the previous:
// < ES6:
var foo = ['a', 'ab', 'abc'];
var bar = foo.map(function(f) {
return f.length;
});
console.log(bar); // 1,2,3
DEMO
The other awesome thing is lexical this... Usually, you'd do something like:
function Foo() {
this.name = name;
this.count = 0;
this.startCounting();
}
Foo.prototype.startCounting = function() {
var self = this;
setInterval(function() {
// this is the Window, not Foo {}, as you might expect
console.log(this); // [object Window]
// that's why we reassign this to self before setInterval()
console.log(self.count);
self.count++;
}, 1000)
}
new Foo();
But that could be rewritten with the arrow like this:
function Foo() {
this.name = name;
this.count = 0;
this.startCounting();
}
Foo.prototype.startCounting = function() {
setInterval(() => {
console.log(this); // [object Object]
console.log(this.count); // 1, 2, 3
this.count++;
}, 1000)
}
new Foo();
DEMO
MDN
More on Syntax
For more, here's a pretty good answer for when to use arrow functions.
These are Arrow Functions
Also known as Fat Arrow Functions. They're a clean and consise way to write function expressions, e.g. function() {}.
Arrow Functions can remove the need of function, return and {} when defining functions. They are one-liners, similar to Lambda Expressions in Java or Python.
Example with no parameters
const queue = ['Dave', 'Sarah', 'Sharon'];
const nextCustomer = () => queue[0];
console.log(nextCustomer()); // 'Dave'
If multiple statements need to be made within the same Arrow Function, you need to wrap, in this example, queue[0] in curley brackets {}. In this case the return statement cannot be omitted.
Example with 1 parameter
const queue = ['Dave', 'Sarah', 'Sharon'];
const addCustomer = name => {
queue.push(name);
};
addCustomer('Toby');
console.log(queue); // ['Dave', 'Sarah', 'Sharon', 'Toby']
You can omit {} from the above.
When there is a single parameter, the brackets () around the parameter can be omitted.
Example with multiple parameters
const addNumbers = (x, y) => x + y
console.log(addNumbers(1, 5)); // 6
A useful example
const fruits = [
{ name: 'Apple', price: 2 },
{ name: 'Bananna', price: 3 },
{ name: 'Pear', price: 1 }
];
If we wanted to get the price of every fruit in a single array, in ES5 we could do:
fruits.map(function(fruit) {
return fruit.price;
}); // [2, 3, 1]
In ES6 with the new Arrow Functions, we can make this more concise:
fruits.map(fruit => fruit.price); // [2, 3, 1]
Additional information on Arrow Functions can be found here.
This would be the "arrow function expression" introduced in ECMAScript 6.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/arrow_functions
For historical purposes (if the wiki page changes later), it is:
An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value. Arrow functions are always anonymous.
just to add another example of what a lambda can do without using map:
a = 10
b = 2
var mixed = (a,b) => a * b;
// OR
var mixed = (a,b) => { (any logic); return a * b };
console.log(mixed(a,b))
// 20
As others have said, it's a new syntax to create functions.
However, this kind of functions differ from normal ones:
They bind the this value. As explained by the spec,
An ArrowFunction does not define local bindings for arguments,
super, this, or new.target. Any reference to arguments,
super, this, or new.target within an ArrowFunction must
resolve to a binding in a lexically enclosing environment. Typically
this will be the Function Environment of an immediately enclosing
function.
Even though an ArrowFunction may contain references to super, the
function object created in step 4 is not made into a method by
performing MakeMethod. An ArrowFunction that references super
is always contained within a non-ArrowFunction and the necessary
state to implement super is accessible via the scope that is
captured by the function object of the ArrowFunction.
They are non-constructors.
That means they have no [[Construct]] internal method, and thus can't be instantiated, e.g.
var f = a => a;
f(123); // 123
new f(); // TypeError: f is not a constructor
I've read, this is a symbol of Arrow Functions in ES6
this
var a2 = a.map(function(s){ return s.length });
using Arrow Function can be written as
var a3 = a.map( s => s.length );
MDN Docs
Dissatisfied with the other answers. The top voted answer as of 2019/3/13 is factually wrong.
The short terse version of what => means is it's a shortcut writing a function AND for binding it to the current this
const foo = a => a * 2;
Is effectively a shortcut for
const foo = function(a) { return a * 2; }.bind(this);
You can see all the things that got shortened. We didn't need function, nor return nor .bind(this) nor even braces or parentheses
A slightly longer example of an arrow function might be
const foo = (width, height) => {
const area = width * height;
return area;
};
Showing that if we want multiple arguments to the function we need parentheses and if we want write more than a single expression we need braces and an explicit return.
It's important to understand the .bind part and it's a big topic. It has to do with what this means in JavaScript.
ALL functions have an implicit parameter called this. How this is set when calling a function depends on how that function is called.
Take
function foo() { console.log(this); }
If you call it normally
function foo() { console.log(this); }
foo();
this will be the global object.
If you're in strict mode
`use strict`;
function foo() { console.log(this); }
foo();
// or
function foo() {
`use strict`;
console.log(this);
}
foo();
It will be undefined
You can set this directly using call or apply
function foo(msg) { console.log(msg, this); }
const obj1 = {abc: 123}
const obj2 = {def: 456}
foo.call(obj1, 'hello'); // prints Hello {abc: 123}
foo.apply(obj2, ['hi']); // prints Hi {def: 456}
You can also set this implicitly using the dot operator .
function foo(msg) { console.log(msg, this); }
const obj = {
abc: 123,
bar: foo,
}
obj.bar('Hola'); // prints Hola {abc:123, bar: f}
A problem comes up when you want to use a function as a callback or a listener. You make class and want to assign a function as the callback that accesses an instance of the class.
class ShowName {
constructor(name, elem) {
this.name = name;
elem.addEventListener('click', function() {
console.log(this.name); // won't work
});
}
}
The code above will not work because when the element fires the event and calls the function the this value will not be the instance of the class.
One common way to solve that problem is to use .bind
class ShowName {
constructor(name, elem) {
this.name = name;
elem.addEventListener('click', function() {
console.log(this.name);
}.bind(this); // <=========== ADDED! ===========
}
}
Because the arrow syntax does the same thing we can write
class ShowName {
constructor(name, elem) {
this.name = name;
elem.addEventListener('click',() => {
console.log(this.name);
});
}
}
bind effectively makes a new function. If bind did not exist you could basically make your own like this
function bind(functionToBind, valueToUseForThis) {
return function(...args) {
functionToBind.call(valueToUseForThis, ...args);
};
}
In older JavaScript without the spread operator it would be
function bind(functionToBind, valueToUseForThis) {
return function() {
functionToBind.apply(valueToUseForThis, arguments);
};
}
Understanding that code requires an understanding of closures but the short version is bind makes a new function that always calls the original function with the this value that was bound to it. Arrow functions do the same thing since they are a shortcut for bind(this)
Adding simple CRUD example with Arrowfunction
//Arrow Function
var customers = [
{
name: 'Dave',
contact:'9192631770'
},
{
name: 'Sarah',
contact:'9192631770'
},
{
name: 'Akhil',
contact:'9928462656'
}],
// No Param READ
getFirstCustomer = () => {
console.log(this);
return customers[0];
};
console.log("First Customer "+JSON.stringify(getFirstCustomer())); // 'Dave'
//1 Param SEARCH
getNthCustomer = index=>{
if( index>customers.length)
{
return "No such thing";
}
else{
return customers[index];
}
};
console.log("Nth Customer is " +JSON.stringify(getNthCustomer(1)));
//2params ADD
addCustomer = (name, contact)=> customers.push({
'name': name,
'contact':contact
});
addCustomer('Hitesh','8888813275');
console.log("Added Customer "+JSON.stringify(customers));
//2 param UPDATE
updateCustomerName = (index, newName)=>{customers[index].name= newName};
updateCustomerName(customers.length-1,"HiteshSahu");
console.log("Updated Customer "+JSON.stringify(customers));
//1 param DELETE
removeCustomer = (customerToRemove) => customers.pop(customerToRemove);
removeCustomer(getFirstCustomer());
console.log("Removed Customer "+JSON.stringify(customers));
Arrow functions which is denoted by symbol (=>) helps you to create anonymous functions and methods. That leads to more shorter syntax. For example, below is a simple “Add” function which returns addition of two numbers.
function Add(num1 , num2 ){
return num1 + num2;
}
The above function becomes shorter by using “Arrow” syntax as shown below.
Above code has two parts as shown in the above diagram: -
Input: — This section specifies the input parameters to the anonymous function.
Logic: — This section comes after the symbol “=>”. This section has the logic of the actual function.
Many developers think that arrow function makes your syntax shorter, simpler and thus makes your code readable.
If you believe the above sentence, then let me assure you it’s a myth. If you think for a moment a properly written function with name is much readable than cryptic functions created in one line using an arrow symbol.
The main use of arrow function is to ensure that code runs in the
callers context.
See the below code in which have a global variable "context" defined , this global variable is accessed inside a function "SomeOtherMethod" which is called from other method "SomeMethod".
This "SomeMethod" has local "context" variable. Now because "SomeOtherMethod" is called from ""SomeMethod" we expect it to display "local context" , but it displays "global context".
var context = “global context”;
function SomeOtherMethod(){
alert(this.context);
}
function SomeMethod(){
this.context = “local context”;
SomeOtherMethod();
}
var instance = new SomeMethod();
But if replace the call by using Arrow function it will display "local context".
var context = "global context";
function SomeMethod(){
this.context = "local context";
SomeOtherMethod = () => {
alert(this.context);
}
SomeOtherMethod();
}
var instance = new SomeMethod();
I would encourage you to read this link ( Arrow function in JavaScript ) which explain all the scenarios of javascript context and in which scenarios the callers context is not respected.
You can also see the demonstration of Arrow function with javascript in this youtube video I made which demonstrates practically the term Context.
As all of the other answers have already said, it's part of ES2015 arrow function syntax. More specifically, it's not an operator, it's a punctuator token that separates the parameters from the body: ArrowFunction : ArrowParameters => ConciseBody. E.g. (params) => { /* body */ }.
As others have stated, regular (traditional) functions use this from the object that called the function, (e.g. a button that was clicked). Instead, arrow functions use this from the object that defines the function.
Consider two almost identical functions:
regular = function() {
' Identical Part Here;
}
arrow = () => {
' Identical Part Here;
}
The snippet below demonstrates the fundamental difference between what this represents for each function. The regular function outputs [object HTMLButtonElement] whereas the arrow function outputs [object Window].
<html>
<button id="btn1">Regular: `this` comes from "this button"</button>
<br><br>
<button id="btn2">Arrow: `this` comes from object that defines the function</button>
<p id="res"/>
<script>
regular = function() {
document.getElementById("res").innerHTML = this;
}
arrow = () => {
document.getElementById("res").innerHTML = this;
}
document.getElementById("btn1").addEventListener("click", regular);
document.getElementById("btn2").addEventListener("click", arrow);
</script>
</html>
ES6 Arrow functions:
In javascript the => is the symbol of an arrow function expression. A arrow function expression does not have its own this binding and therefore cannot be used as a constructor function. for example:
var words = 'hi from outside object';
let obj = {
words: 'hi from inside object',
talk1: () => {console.log(this.words)},
talk2: function () {console.log(this.words)}
}
obj.talk1(); // doesn't have its own this binding, this === window
obj.talk2(); // does have its own this binding, this is obj
Rules of using arrow functions:
If there is exactly one argument you can omit the parentheses of the argument.
If you return an expression and do this on the same line you can omit the {} and the return statement
For example:
let times2 = val => val * 2;
// It is on the same line and returns an expression therefore the {} are ommited and the expression returns implictly
// there also is only one argument, therefore the parentheses around the argument are omitted
console.log(times2(3));
JavaScript arrow functions are roughly the equivalent of lambda functions in python or blocks in Ruby. These are anonymous functions with their own special syntax and operate in the context of their enclosing scope. This mean they do not have their own "this" but instead access the one from the immediate enclosing function.
From the ECMA standard:
An ArrowFunction does not define local bindings for arguments,
super, this, or new.target. Any reference to arguments, super, this, or new.target within an ArrowFunction must resolve to a
binding in a lexically enclosing environment. Typically this will be
the Function Environment of an immediately enclosing function.
Often you can read "an arrow function expression is a compact alternative to a traditional function expression", this is not a correct. Arrow function are NOT a shorthand for traditional function, they behave differently that traditional function.
Syntax
// Traditional Function
// Create their own scope inside the function
function (a){
return a + 100;
}
// Arrow Function
// Do NOT create their own scope
// (Each step along the way is a valid "arrow function")
// 1. Remove the word "function" and place arrow between the argument and opening body bracket
(a) => {
return a + 100;
}
// 2. Remove the body braces and word "return" -- the return is implied.
(a) => a + 100;
// 3. Remove the argument parentheses (only valid with exactly one argument)
a => a + 100;

arrow function and this

I'm browsing twitter and found this tweet:
https://twitter.com/_ericelliott/status/855598297939144704
Here is the code from the tweet:
const double = () => this.x * 2;
const numDouble = double.bind({ x: 5 });
numDouble();
When you run this snippet in console it'll produce NaN.
How?
Author is explicitly binding the value of x, but still it's showing NaN.
Author is also specifying that arrow function can't bind this. As i know that arrow function lexically bind the value of this form surrounding scope. Then why author is claiming so?
Please clarify my doubts and Thanks in advance for the help.
Arrow functions don't bind this. As per MDN:
No binding of this
Until arrow functions, every new function defined its own this value
(a new object in the case of a constructor, undefined in strict mode
function calls, the context object if the function is called as an
"object method", etc.). This proved to be annoying with an
object-oriented style of programming.
So this in your example will be the global object window which apparently don't have a property called x.
Example:
function foo() {
let arrow = () => {
console.log(this); // will use foo's this as arrow will never have its own this
}
arrow.call({"x": "x"}); // ... even if we specify it using bind, call, or apply
}
foo.call({"y": "y"}); // specifying the this for foo (this value will eventually be used by arrow because it will be availbale in its scope)
The key thing to remember is:
Arrow functions close over this, exactly the way that functions close over variables. (In fact, it's the same mechanism.) Whatever this is where the arrow function is created is what this will be during a call to that arrow function. It will never be anything else. Arrow functions ignore the this they're called with.
If you remember that, you'll never be confused by this in an arrow function again.
When you run this snippet in console it'll produce NaN. How? Author is explicitly binding the value of x, but still it's showing NaN.
numDouble = double.bind({ x: 5 }) creates a new function (numDouble) that, when called, will call the original function (double) with this set to the value you provide as bind's first argument ({ x: 5 }). But since arrow functions ignore the this they're called with, bind can't control what this they use.
Author is also specifying that arrow function can't bind this. As i know that arrow function lexically bind the value of this form surrounding scope.
Right, which means you can't change it. Lexical binding is the way closures work. This arrow function:
const a = () => {
console.log(typeof this);
};
treats this exactly the way this traditional function treats thisWhereFunctionWasCreated:
const thisWhereFunctionWasCreated = this;
const t = function() {
console.log(typeof thisWhereFunctionWasCreated);
};
Just like you can't change what thisWhereFunctionWasCreated variable t uses when you call it, you can't change what this a uses when you call it. (If thisWhereFunctionWasCreated weren't a const, you could change the value it holds, but not which thisWhereFunctionWasCreated variable t uses. But it's a constant in that example because this is a constant.)
Since an arrow function completely ignores the this it was called with, it doesn't matter what mechanism you use to try to tell the arrow function what this to use, it won't work. Whether you specify this implicitly by calling the function as a method (obj.arrow()), or via call or apply (arrow.call(obj)), or via bind (const boundArrow = arrow.bind(obj); boundArrow();), it will still use the this it closes over instead:
"use strict";
function Ctor() {
// `this` will be the object created by `new Ctor`; grab it
this.name = "outerThis";
const outerThis = this;
// `traditional` doesn't close over `this`, so you CAN change
// what `this` it uses when you call it, in various ways
function traditional(testNum) {
console.log(testNum, "traditional:", getName(this));
}
// `arrow` closes over `this`, so you CAN'T change
// what `this` it uses when you call it
const arrow = testNum => {
console.log(testNum, "arrow: ", getName(this));
};
// Remember that the `this` in a direct call is the global
// object in loose mode, `undefined` in strict mode; this
// code is in strict mode
console.log("Direct call (default `this`):");
traditional(1); // 1 traditional: window
arrow(1); // 1 arrow: outerThis
console.log("`obj.xyz()`:");
const obj = {
name: "obj",
arrow,
traditional
};
obj.traditional(2); // 2 traditional: obj
obj.arrow(2); // 2 arrow: outerThis
console.log("Using `call`:");
traditional.call(obj, 3); // 3 traditional: obj
arrow.call(obj, 3); // 3 arrow: outerThis
console.log("Using `bind` and calling result:");
const boundTraditional = traditional.bind(obj);
const boundArrow = arrow.bind(obj);
boundTraditional(4); // 4 traditional: obj
boundArrow(4); // 4 arrow: outerThis
}
function getName(t) {
switch (t) {
case undefined:
return "undefined";
case window:
return "window";
default:
return t.name;
}
}
new Ctor();
.as-console-wrapper {
max-height: 100% !important;
}
The only thing bind can do when called on an arrow function is bind arguments to it:
const arrow = (x, y) => x + y;
console.log(arrow(2, 3)); // 5
const arrowWith2 = arrow.bind(null, 2);
console.log(arrowWith2(3)); // 5
const arrowWith2And3 = arrow.bind(null, 2, 3);
console.log(arrowWith2And3()); // 5
(It also sets the name of the resulting function to "bound x" [where x is the name of the original function. So arrowWith2.name in the above is "bound arrow".)

What does "this" refer to in arrow functions in ES6?

I've read in several places that the key difference is that this is lexically bound in arrow functions. That's all well and good, but I don't actually know what that means.
I know it means it's unique within the confines of the braces defining the function's body, but I couldn't actually tell you the output of the following code, because I have no idea what this is referring to, unless it's referring to the fat arrow function itself....which doesn't seem useful.
var testFunction = () => {
console.log(this)
};
testFunction();
Arrow functions capture the this value of the enclosing context
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}
var p = new Person();
So, to directly answer your question, this inside your arrow function would have the same value as it did right before the arrow function was assigned.
In order to provide the big picture I'm going to explain both, dynamic and lexical binding.
Dynamic Name Binding
this refers to the object the method is called on. This is a regularly to be read sentence on SO. But it is still only a phrase, pretty abstract. Is there a corresponding code pattern to this sentence?
Yes there is:
const o = {
m() { console.log(this) }
}
// the important patterns: applying methods
o.m(); // logs o
o["m"](); // logs o
m is a method because it relies on this. o.m() or o["m"]() means m is applied to o. These patterns are the Javascript translation to our famous phrase.
There is another important code pattern that you should pay attention to:
"use strict";
const o = {
m() { console.log(this) }
}
// m is passed to f as a callback
function f(m) { m() }
// another important pattern: passing methods
f(o.m); // logs undefined
f(o["m"]); // logs undefined
It is very similar to the previous pattern, only the parenthesis are missing. But the consequences are considerable: When you pass m to the function f, you pull outm of its object/context o. It is uprooted now and this refers to nothing (strict mode assumed).
Lexical (or Static) Name Binding
Arrow functions don't have their own this/super/arguments binding. They inherit them from their parent lexical scope:
const toString = Object.prototype.toString;
const o = {
foo: () => console.log("window", toString.call(this)),
bar() {
const baz = () => console.log("o", toString.call(this));
baz();
}
}
o.foo() // logs window [object Window]
o.bar() // logs o [object Object]
Apart from the global scope (Window in browsers) only functions are able to form a scope in Javascript (and {} blocks in ES2015). When the o.foo arrow function is called there is no surrounding function from which baz could inherit its this. Consequently it captures the this binding of the global scope which is bound to the Window object.
When baz is invoked by o.bar, the arrow function is surrounded by o.bar (o.bar forms its parent lexical scope) and can inherit o.bar's this binding. o.bar was called on o and thus its this is bound to o.
Hope this code show could give you clearer idea. Basically, 'this' in arrow function is the current context version of 'this'. See the code:
// 'this' in normal function & arrow function
var this1 = {
number: 123,
logFunction: function () { console.log(this); },
logArrow: () => console.log(this)
};
this1.logFunction(); // Object { number: 123}
this1.logArrow(); // Window
Arrow function this is pointing to the surrounding parent in Es6, means it doesn't scope like anonymous functions in ES5...
It's very useful way to avoid assigning var self to this which is widely used in ES5...
Look at the example below, assigning a function inside an object:
var checkThis = {
normalFunction: function () { console.log(this); },
arrowFunction: () => console.log(this)
};
checkThis.normalFunction(); //Object {}
checkThis.arrowFunction(); //Window {external: Object, chrome: Object, document: document, tmpDebug: "", j: 0…}
You can try to understand it by following the way below
// whatever here it is, function or fat arrow or literally object declare
// in short, a pair of curly braces should be appeared here, eg:
function f() {
// the 'this' here is the 'this' in fat arrow function below, they are
// bind together right here
// if 'this' is meaningful here, eg. this === awesomeObject is true
console.log(this) // [object awesomeObject]
let a = (...param) => {
// 'this is meaningful here too.
console.log(this) // [object awesomeObject]
}
so 'this' in fat arrow function is not bound, means you can not make anything bind to 'this' here, .apply won't, .call won't, .bind won't. 'this' in fat arrow function is bound when you write down the code text in your text editor. 'this' in fat arrow function is literally meaningful here. What your code write here in text editor is what your app run there in repl. What 'this' bound in fat arror will never change unless you change it in text editor.
Sorry for my pool English...
Arrow function never binds with this keyword
var env = "globalOutside";
var checkThis = {env: "insideNewObject", arrowFunc: () => {
console.log("environment: ", this.env);
} }
checkThis.arrowFunc() // expected answer is environment: globalOutside
// Now General function
var env = "globalOutside";
var checkThis = {env: "insideNewObject", generalFunc: function() {
console.log("environment: ", this.env);
} }
checkThis.generalFunc() // expected answer is enviroment: insideNewObject
// Hence proving that arrow function never binds with 'this'
this will always refer to the global object when used inside an arrow function. Use the regular function declaration to refer to the local object. Also, you can use the object name as the context (object.method, not this.method) for it to refer to the local object instead of the global(window).
In another example, if you click the age button below
<script>
var person = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: function() {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
var person2 = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: () => {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
</script>
<input type=button onClick="alert(person2.age());" value="Age">
it will throw an exception like this
×JavaScript error: Uncaught TypeError: Cannot read property
'getFullYear' of undefined on line 18
But if you change person2's this line
return new Date().getFullYear() - this.dob.getFullYear();
to
return new Date().getFullYear() - person2.dob.getFullYear();
it will work because this scope has changed in person2
Differences between arrow functions to regular functions: (taken from w3schools)
With arrow functions there are no binding of this.
In regular functions the this keyword represented the object that called the function, which could be the window, the document, a button or whatever.
With arrow functions the this keyword always represents the object that defined the arrow function.
// Regular Function:
hello = function() {
document.getElementById("demo").innerHTML += this;
}
// The window object calls the function:
window.addEventListener("load", hello);
// A button object calls the function:
document.getElementById("btn").addEventListener("click", hello);
// -------------------------------------------
// Arrow function
hello2 = () => {
document.getElementById("demo2").innerHTML += this;
}
// The window object calls the function:
window.addEventListener("load", hello2);
// A button object calls the function:
document.getElementById("btn2").addEventListener("click", hello2);
<p><i>With a regular function this represents the <b>object that calls the function</b>:</i></p>
<button id='btn'>click me regular function</button>
<p id="demo">Regular function: </p>
<hr>
<p><i>With arrow function this represents the <b>owner of the function(=the window object)</b>:</i></p>
<button id='btn2'>click me arrow function</button>
<p id="demo2">Arrow function: </p>
A related issue:
Came from - Why can't I access `this` within an arrow function?
We know below from here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Does not have its own bindings to this or super, and should not be used as methods.
Arrow functions establish "this" based on the scope the Arrow function is defined within.
Had a issue with this using arrow functions, so created a class (can be function), and class variable is accessed in arrow function, thereby achieved smaller functions using arrow functions without function keyword:
class MyClassOrFunction {
values = [];
size = () => this.values.length;
isEmpty = () => this.size() === 0;
}
let obj = new MyClassOrFunction();
obj.size(); // function call here
You can also have a getter like this, that does not have function keyword, but a bit longer due to return statement, also can access other member functions:
class MyClassOrFunction {
values = [];
size = () => this.values.length;
get length() { return this.size(); }
}
let obj = new MyClassOrFunction();
obj.length; // NOTE: no function call here

Categories

Resources