user431619
user431619

Reputation:

Javascript - arrow functions this in event handler?

I'm new to ES6, and can't quite get this to work:

$(this) returns undefined on click?

dom.videoLinks.click((e) => {
            e.preventDefault();
            console.log($(this));
            var self = $(this),
                url = self.attr(configuration.attribute);

            eventHandlers.showVideo(url);

            // Deactivate any active video thumbs
            dom.videoLinks.filter('.video-selected').removeClass('video-selected');

            // Activate selected video thumb
            self.addClass('video-selected');
        });

However if I change it so not be an arrow function like so, it works as expected?:

dom.videoLinks.click(function(e) {
            e.preventDefault();
            console.log(this);
            console.log($(this));
            var self = e.this,
                url = self.attr(configuration.attribute);

            eventHandlers.showVideo(url);

            // Deactivate any active video thumbs
            dom.videoLinks.filter('.video-selected').removeClass('video-selected');

            // Activate selected video thumb
            self.addClass('video-selected');
        });

So how would I go about it if I use an arrow function in the callback?

Upvotes: 18

Views: 22531

Answers (5)

Mubarrat Hasan
Mubarrat Hasan

Reputation: 304

The handling of this is also different in arrow functions compared to regular functions.

In short, with arrow functions, there is no binding of this.

In regular functions, the this keyword represents the object called the function, which could be the window, the document, a button, or whatever.

In arrow functions, the this keyword always represents the object that defined the arrow function.

To get the object called the arrow function, you must use event.currentTarget instead of this.

You defined event as the parameter e in your case.

Upvotes: -1

The Process
The Process

Reputation: 5953

With arrow function as a callback, instead of using this to get the element to which the handler is bound, you should use event.currentTarget.
Value of this inside an arrow function is determined by where the arrow function is defined, not where it is used.
So from now on, keep in mind that event.currentTarget always refers to the DOM element whose EventListeners are currently being processed.


.currentTarget vs .target

Use event.currentTarget instead of event.target because of event bubbling/capturing:

  • event.currentTarget- is the element that has the event listener attached to.
  • event.target- is the element that triggered the event.

From the documentation:

currentTarget of type EventTarget, readonly Used to indicate the EventTarget whose EventListeners are currently being processed. This is particularly useful during capturing and bubbling.

Check the basic example in the below snippet

var parent = document.getElementById('parent');
parent.addEventListener('click', function(e) {
  
  document.getElementById('msg').innerHTML = "this: " + this.id +
    "<br> currentTarget: " + e.currentTarget.id +
    "<br>target: " + e.target.id;
});

$('#parent').on('click', function(e) {

  $('#jQmsg').html("*jQuery<br>this: " + $(this).prop('id')
                   + "<br>currenTarget: " + $(e.currentTarget).prop('id') 
                   + "<br>target: " + $(e.target).prop('id'));
});

$('#parent').on('click', e => $('#arrmsg').html('*Arrow function <br> currentTarget: ' + e.currentTarget.id));
#parent {background-color:red; width:250px; height:220px;}
#child {background-color:yellow;height:120px;width:120px;margin:0 auto;}
#grand-child {background-color:blue;height:50px;width:50px;margin:0 auto;}
#msg, #jQmsg, #arrmsg {font-size:16px;font-weight:600;background-color:#eee;font-family:sans-serif;color:navy;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

  <div id="parent">Parent-(attached event handler)<br><br>
    <div id="child"> Child<br><br>
      <p id="grand-child">Grand Child</p>
    </div>
  </div>
 
  <div id="msg"></div><br>
  <div id="jQmsg"></div><br>
  <div id="arrmsg"></div>

Upvotes: 40

Ginden
Ginden

Reputation: 5316

arrow functions and this selector?

Arrow functions retain this from enclosing context. Eg.

obj.method = function(){
    console.log(this);
    $('a').click(e=>{
            console.log(this);
    })
};
obj.method(); // logs obj
$('a').click(); // logs obj

So how would I go about it if I use an arrow function in the callback?

You already can - to access event target you can use something like $(e.target), but beware of bubbling. So I recommend to use normal functions instead as callbacks.

Upvotes: 2

smnbbrv
smnbbrv

Reputation: 24551

You can use $(event.target) instead of $(this) even inside of an arrow function. Arrow functions are preserving this of the scope where they were defined. In your case it is undefined.

Upvotes: 4

Quentin
Quentin

Reputation: 943579

You wouldn't.

Changing the value of this is the primary point of using an arrow function.

If you don't want to do that then an arrow function is the wrong tool for the job.

Upvotes: 10

Related Questions