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.
Related
This question already has answers here:
Methods in ES6 objects: using arrow functions
(6 answers)
Are 'Arrow Functions' and 'Functions' equivalent / interchangeable?
(4 answers)
Closed 2 years ago.
I am sure that I misunderstand how i can access function properties from one of its prototypes .
i may got -10 because of this question , but I truly need help in understanding why it always returns undefined
here is a reference
function lookup() {
if (!(this instanceof lookup)) {
return new lookup();
}
this.url = "/administration/lookups";
};
lookup.prototype.partial_create = () => {
alert(this.url);
};
var lookup1 = function(){
this.url = "/administration/lookups";
}
lookup1.prototype.makealert = ()=>{
alert(this.url);
}
$(()=>{
new lookup().partial_create();
new lookup1().makealert();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
It's because you've defined both the prototype methods as arrow functions - which behave differently from other functions with regard to the this keyword. (This indeed is the main point of using arrow functions in the first place - but they are misplaced here.) In particular (as you can read at the above link), arrow functions use the this of their enclosing scope - which here is the global scope. So this does not refer to your instance of lookup, but to the global object - hence this.url is just the global variable url, which (since you haven't defined such a variable) is undefined.
To show the difference, run the below snippet - which is identical to yours with the arrow functions replaced by "regular" function declarations. This now works as you presumably intend:
function lookup() {
if (!(this instanceof lookup)) {
return new lookup();
}
this.url = "/administration/lookups";
};
lookup.prototype.partial_create = function() {
alert(this.url);
};
var lookup1 = function(){
this.url = "/administration/lookups";
}
lookup1.prototype.makealert = function() {
alert(this.url);
}
$(()=>{
new lookup().partial_create();
new lookup1().makealert();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
This question already has answers here:
How do JavaScript closures work?
(86 answers)
Closed 3 years ago.
How do I use the variable from the outer scope of the function. I have created this simple example here
var view = {
init(){
const targetOne = document.querySelector(".targetOne");
const targetTwo = document.querySelector(".targetTwo");
var val = "outer scope";
targetOne.addEventListener('click', (e) => {
console.log('target one', val)
});
targetTwo.addEventListener('click', this.handleEvent);
},
handleEvent(e) {
console.log('targetTwo ', val);
}
}
view.init();
JS fiddle link: https://jsfiddle.net/jr7b521x/50/
For the targetOne callback I can use the variable val, but when i define a function for the targetTwo callback, that variable val is not defined in the scope. I feel like I am missing something very simple here, I refreshed on scope chaining and closure but I am not able to get it
the variable val is within the scope of the init () function
for you to get it in the handleEvent function you will need to pass it by parameter or it must be a property of the view object
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.
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`
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
How do I write a named arrow function in ES2015?
(8 answers)
Closed 7 years ago.
For example in the Class constructor:
Socket.on('user:join', onUserJoin);
'onUserJoin' is declared as a method of the class but is being called by socket.io so the 'this' is not my Class. A way to resolve this is to use the '=>' function.
example:
Socket.on('user:join', (data)=>{
this.isOnline = true;
});
Now 'this' is my class, but how do I reference this anonymous function to unsubscribe ?
socket.removeListener('user:join', ????);
I did try this:
let self;
class RoomController {
constructor() {
self = this;
}
...
}
and reference the self in the methods but the self was being shared across sockets...
naming the anonymous function could solve it but I preferred for my case the bind option.
You can use Function.prototype.bind.
Socket.on('user:join', onUserJoin.bind(this));
This ensures that onUserJoin has the correct context, which will be the instance of your class.
You can always bind the arrow functions to the names.
For example,
class RoomController {
constructor() {
this.flag = true;
}
// Assign the arrow function to the name `setFlag`
setFlag = (v) => this.flag = v;
}
let r = new RoomController();
function tester(func) {
func(false);
console.log(r.flag);
// false
func(true);
console.log(r.flag);
// true
}
// Now you can pass the function around, `this` will still refer the object `r`
tester(r.setFlag);