Reputation: 1038
I have this code block that I use to bind an event listener to every anchor tag with a #
href. I decided to convert event listener's callback function to an arrow function but while the original code works, the modified one results in an error: TypeError: undefined has no properties
. I have used arrow callback functions many times before and they do work fine. What makes it break in this instance?
Original code that works:
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth',
});
});
});
Broken arrow callback function:
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
anchor.addEventListener('click', (e) => {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth',
});
});
});
Edit: I fixed the issue like this but I still cannot figure out how these two are different
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
anchor.addEventListener('click', (e) => {
e.preventDefault();
anchor.scrollIntoView({
behavior: 'smooth',
});
});
});
Or:
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
anchor.addEventListener('click', (e) => {
e.preventDefault();
e.target.scrollIntoView({
behavior: 'smooth',
});
});
});
Upvotes: 1
Views: 205
Reputation: 686
The problem is because the use of this
inside your function.
According to MDN:
An arrow function expression is a syntactically compact alternative to a regular function expression, although without its own bindings to the this, arguments, super, or new.target keywords.
As @Ben Aston already mentioned in the comments you could change this.getAttribute
to event.target.getAttribute
Upvotes: 2