nook
nook

Reputation: 1884

How to use the "this" keyword when calling a function in an anonymous function in Javascript?

I am looking to call a function that was originally just an anonymous function, but it turned out I need this function 3 times in my code. So I defined a function like this:

function saveButton() {
  this.parentElement.parentElement.querySelector('h3').innerHTML = this.parentElement.querySelector('input[name="task-title"]').value;
  this.parentElement.parentElement.querySelector('p').innerHTML = this.parentElement.querySelector('textarea').value;
  this.parentElement.parentElement.querySelector('.popup').className = 'popup hidden';
  this.parentElement.parentElement.querySelector('.overlay').className = 'overlay hidden';
  saveWork();
};

I want to call this function in an anonymous function like this :

confirmButton.onclick = function()
    saveButton();
};

But afterwards I realized that I couldn't use the this in the anonymous function. How can I call confirmButton() in the anonymous function?

Upvotes: 1

Views: 185

Answers (3)

tehabstract
tehabstract

Reputation: 549

Have you tried using function expressions? Essentially it means assigning a function to a variable. Read this answer to learn about the differences between function expressions and function declarations.

As for your question, most of the time it's this case:

You want to use the parent scope of a given anonymous function.

If thats the case, I would recommend this neat little trick:

var self = this;

this.saveButton = function() { // or self.saveButton...
  this.parentElement.parentElement.querySelector('h3').innerHTML = this.parentElement.querySelector('input[name="task-title"]').value;
  this.parentElement.parentElement.querySelector('p').innerHTML = this.parentElement.querySelector('textarea').value;
  this.parentElement.parentElement.querySelector('.popup').className = 'popup hidden';
  this.parentElement.parentElement.querySelector('.overlay').className = 'overlay hidden';
  saveWork();
};

confirmButton.onclick = function() {
    self.saveButton();
}

This trick can be used in any level of scope depth, just don't pollute the global namespace :)

Upvotes: 1

rodrigocfd
rodrigocfd

Reputation: 8043

By looking at the code fragment you posted, and guessing a few things, I suggest the following refactoring:

function saveButton(parentElem) {
  var myParent = parentElem || this.parentElement;
  myParent.parentElement.querySelector('h3').innerHTML = myParent.querySelector('input[name="task-title"]').value;
  myParent.parentElement.querySelector('p').innerHTML = myParent.querySelector('textarea').value;
  myParent.parentElement.querySelector('.popup').className = 'popup hidden';
  myParent.parentElement.querySelector('.overlay').className = 'overlay hidden';
  saveWork();
}

confirmButton.onclick = function() {
  // I suppose when this function is called somewhere else,
  // you actually know who is the parent element, so:
  saveButton(document.querySelector('.theParentElement'));
};

// If you calling it somewhere where "this" is available,
// then simply call the function with no arguments:
saveButton();

Maybe some variation of the example above can help you. Other than that, I can't think of a better answer without looking at a greater portion of your code.

Upvotes: 0

fila90
fila90

Reputation: 1459

confirmButton.onclick = saveButton;

or

confirmButton.onclick = function(){
    saveButton.call(this);
};

although it's not a good practice to have the same name for DOM node and a function that you want to call. rename your function into something that makes more sense like buttonClick

Upvotes: 2

Related Questions