This question already has answers here:
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 6 years ago.
I'm hoping I got the right area to ask for this...
Below is some code from two files I'm working on. When I change anything with 'this.' in the function to an arrow function, the code no longer functions as expected.
Is someone able to explain what I'm doing wrong? Do I need to do something differently when using arrow functions? Am I using 'this.' incorrectly to begin with? Should I not be using arrow functions in this way?
Help is greatly appreciated.
client/views/jobList.html
{{#each jobs}}
<tr>
<td>{{jobID}}</td>
<td>{{user.fullname}}</td>
<td>{{product.type}}</td>
<td>{{shortDesc}}</td>
<td>{{formattedDate}}</td>
<td>{{phone}}</td>
<td>{{user.username}}</td>
<td>{{jobType}}</td>
<td>{{product.brand}}</td>
<td>{{product.type}}</td>
<td>{{product.model}}</td>
</tr>
{{/each}}
client/views/jobList.js
Template.jobList.helpers({
jobs: ()=> Jobs.find({}, {sort: {jobDate: 1}}),
formattedDate: function() { // Changing this to arrow function breaks functionality
let d = this.jobDate;
let e = formatDate(d);
return e;
},
shortDesc: function () { // Changing this to arrow function breaks functionality
if (this.description.length > 40) {
return this.description.substr(0, 50) + '...';
} else {
return this.description
}
},
jobID: function () { // Changing this to arrow function breaks functionality
let a = this.jobNum;
let e = this.jobType.substr(0, 1);
return e + a
}
});
One of the fundamental things about arrow functions is that they inherit (close over) the this in the context in which they're created. Your code relies on this being set by the way the function is called, so arrow functions aren't a good choice there.
Here's an illustration of the difference and the problem:
var obj = {
foo: () => {
console.log("foo: this.prop:", this.prop);
},
bar: function() {
console.log("bar: this.prop:", this.prop);
},
prop: "the property"
};
obj.foo(); // Doesn't show `prop` because `this` != `obj`
obj.bar(); // Does show `prop` because `this` == `obj`
Related
This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
What does "this" refer to in arrow functions in ES6?
(10 answers)
Closed 1 year ago.
I'm new to javascript and having trouble understanding the difference between arrow function and normal function when including this keyword, here is the example I read from MDN:
var obj = { // does not create a new scope
i: 10,
b: () => console.log(this.i, this),
c: function() {
console.log(this.i, this);
}
}
obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}
In this example arrow function b() can not access i attribute in the object because it references the window
var obj = {
count : 10,
doSomethingLater : function(){ // of course, arrow functions are not suited for methods
setTimeout( () => { // since the arrow function was created within the "obj", it assumes the object's "this"
this.count++;
console.log(this.count);
}, 300);
}
}
obj.doSomethingLater(); //log 11 on the console
However, in the second example, code within the arrow function can access the count attribute. Both functions are defined within the object but only the second function can access the object's attribute, could someone give me some hints why is that? Thanks in advance!
This question already has answers here:
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 5 years ago.
let objNewWay = {
width:400,
height:300,
area: () => this.width*this.height
};
console.log(objNewWay.area()); // NaN
let objOldWay = {
width:400,
height:300,
area: function() {
return this.width*this.height;
}
};
console.log(objOldWay.area()); // 120000
I don't understand why the arrow function in Javascript object does not seems to work. If you look at the code above, the first console.log prints NaN, and the second prints the number as expected.
https://jsbin.com/pazazikayi/edit?js,console
From the documentation :
An arrow function expression has a shorter syntax than a function
expression and does not bind its own this, arguments, super, or
new.target. These function expressions are best suited for non-method
functions, and they cannot be used as constructors.
You have to use the old way like you already showed
area: function() {
return this.width*this.height;
}
if you still want to use the arrow function, you have to call the object itself
let objNewWay = {
width:400,
height:300,
area: ()=> objNewWay.width*objNewWay.height
};
console.log(objNewWay.area()); // NaN
The arrow functions are not lambdas, and the way you use it will refer to a different scope from your object's.
For instance, from the console:
let theObj = {
whereAmI: () => console.log(this)
}
theObj.whereAmI();
// Window...
If you want to use this keyword, use to the area: function(){} way.
This question already has answers here:
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 6 years ago.
I have two cases
const test = {
foo: function (){
this.bar();
},
bar: function (){
console.log('bar');
}
}
test.foo();
in this case, everything works correctly.
const test = {
foo: () => {
this.bar();
},
bar: () => {
console.log('bar');
}
}
test.foo();
In second case I get error:
Uncaught TypeError: Cannot read property 'bar' of undefined
I know I can wrote test.bar() in foo function, but I'm interested why this not available in arrow functions scope in this case.
Normally, the value of this in a function depends on how that function is called.
Arrow functions import the value of this from the scope in which the function was created.
In the middle of an object literal, the value of this will depend on what is around the object literal, but certainly won't be the object itself.
This question already has answers here:
What's the meaning of "=>" (an arrow formed from equals & greater than) in JavaScript?
(14 answers)
Closed 6 years ago.
I'm reading through the annotated source for the Parsley javascript library, and I keep seeing notations that I don't fully understand. Google searches aren't really helping as google is ignoring "() =>" or "=>" as useful search terms.
Here's an example:
if (event) {
this.submitEvent = $.extend({}, event, {preventDefault: () => {
ParsleyUtils.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
this.validationResult = false;
}});
}
I can guess what is happening, but I don't understand the syntax or the name of the function / lambda declaration or pattern.
What is the name of the pattern or style of function declaration? What is its purpose?
These are referred to as arrow functions, which are basically an ES6 approach to leverage functions in a slightly new way. For some simple background on whats going on, MDN explains the idea as such
Two factors influenced the introduction of arrow functions: shorter functions and lexical this.
Check out this example...
var self = this;
setInterval(function growUp() {
// The callback refers to the `self` variable of which
// the value is the expected object.
self.age++;
}, 1000);
with arrow syntax becomes
// `this` here is the same as `this` in the setInterval
setInterval(() => {
this.age++; // `this` properly refers to this in the outer scope
}, 1000);
So with your example, the "traditional" representation could be as such...
var self = this;
if (event) {
self.submitEvent = $.extend({}, event, { preventDefault: function() {
// [...]
self.validationResult = false;
}});
}
Another great use of arrow functions is for one liners
[1,2,3,4].map(num => num * 2); // [2,4,6,8]
This question already has answers here:
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 6 years ago.
Right now in my helper is using function()
updateCVId: function() {
return this._id; //return the real id
}
It's working, but if I use ()=>
updateCVId:()=> {
return this._id; //return undefined
}
then this._id is undefined.
The same is for the events:
'click .foo': function(evt, tmp) {
console.log(this._id); //log the real id
}
and
'click .foo': (evt, tmp)=> {
console.log(this._id); //log undefined
}
Can someone tell me if I use ()=> , how to get the data?
Thank you guys.
Arrow functions => are designed to automatically bind the context this from lexical scope. In your situation this is undefined, because it runs in 'strict mode'.
To solve your problem you can:
1) Use a regular function, as you did already:
var actions = {
//...
updateCVId: function() {
return this._id; //return the real id
}
//...
};
2) Use an ES6 shorthand function notation:
var actions = {
//...
updateCVId() {
return this._id; //return the real id
}
//...
};
The difference between function() {} and => is in the this context and how the invocation affects this.
In function() {} this is determined by the way function is invoked. If invoking it as a method on the object, this will be the object itself: actions.updateCVId().
I call it soft linked this.
In an arrow function case => this is automatically bound to this of the lexical scope where the function is defined. In your example it's an undefined, which is default case for 'strict mode'.
No matter how the arrow function is invoked later, it will have this as undefined.
I call it hard linked this.
You can find more details about this keyword in this article.