Can someone please explain why defining a prototype function with lambda expression doesn\'t work? I thought this must be asked before but couldn\'t find it.
One of the chief features of arrow functions is that they close over the this
from the context in which they're created; they don't get it based on how they're called like other functions do. So...
// ...whatever `this` is *here*
Book.prototype.printTitle2 = () => {
// ...is what `this` will be *here*
console.log(this.title);
};
But your function relies on this
varying depending on how it's called.
This just isn't a use-case for arrow functions. Use a normal function:
Book.prototype.printTitle2 = function() {
console.log(this.title);
};
Or better yet, use the new class
syntax:
class Book {
constructor(title, year) {
this.title = title;
this.year = year;
}
printTitle2() {
console.log(this.title);
}
}
The Arrow function
would resolve the context this
belongs to the scope where the function was defined. I believe you have defined that function in window
scope. So the this
will point to window
in your function.
You can use normal anonymous function
here. And we have to be careful while using arrow functions.
In addition to @t-j-crowder's answer, I wanted to leave a test case (mocha assert) which you can use to visualize which is not working.
Also you can read more about the scope of arrow functions here:
You Don't Know JS
by Kyle Simpson, who explains this
in detail.
Basically, an arrow function's this
points to the surrounding context of the current context, which comes in handy if you have enclosing functions.
What it does is basically doing the var self = this;
thing.
Or as Kyle says:
[...] Lexical
this
in the arrow function callback in the previous snippet now points to the same value as in the enclosingmakeRequest(..)
function. In other words,=>
is a syntactic stand-in forvar self = this
.In cases where
var self = this
(or, alternatively, a function.bind(this)
call) would normally be helpful,=>
arrow functions are a nicer alternative operating on the same principle. [...]
You can test it yourself with my gist: https://gist.github.com/jay-bricksoft/96738dd8a48ceb9f517e914b834cc1ee
In my test case this was the output:
Lambda
function(){}
√ should equal function´s type
1) should have equal context as function
2) should be able to be used as constructor
1 passing (39ms)
2 failing
1) Lambda function(){} should have equal context as function:
AssertionError: 'undefined' == 'string'
+ expected - actual
-undefined
+string
at Context.<anonymous> (test\index.js:29:14)
2) Lambda function(){} should be able to be used as constructor:
TypeError: construct_l is not a constructor
at Context.<anonymous> (test\index.js:34:20)
EDIT: added example / reference to Kyle Simpson's "You Don't Know ES6" https://github.com/getify/You-Dont-Know-JS/tree/master/es6%20%26%20beyond