This question has already been answered:

There is code, a piece on jquery - everything works fine (the first button), but if I click on the second button to which the event is registered using addEventListener, I lose context, that is the button, this is the ajax options object.

How then, when clicking the second button, call _.setText() from within getAjax() ?

enter image description here

 $(function() { var _ = { initJquery: function() { var that = this; $('#one').on('click', function() { that.getAjax(); }); }, initJs: function() { $('#two')[0].addEventListener('click', this.getAjax); }, setText: function(text) { $('.update').html(text); }, getAjax: function() { var that = this; $.ajax({ url: 'txt.txt', type: 'POST', dataType: 'text' }) .done(function(resp) { console.log('this'); console.log(this); console.log('that'); console.log(that); // ΠΏΡ€ΠΈ Π½Π°ΠΆΠ°Ρ‚ΠΈΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΉ ΠΊΠ½ΠΎΠΏΠΊΠΈ всё Ρ…ΠΎΡ€ΠΎΡˆΠΎ // Ρ‚ΡƒΡ‚ Ρ‚Π΅Ρ€ΡΡŽ контСкст ΠΏΡ€ΠΈ Π½Π°ΠΆΠ°Ρ‚ΠΈΠΈ Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΊΠ½ΠΎΠΏΠΊΠΈ addEventListener that.setText(resp); }) .fail(function() { console.log("error"); }); } }; _.initJquery(); _.initJs(); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <input type="button" id="one" value="Кнопка 1"> <input type="button" id="two" value="Кнопка 2"> <div class="update"></div> 

Result

Thank you all, figured out. It was necessary so:

 .done(function() { this.setText(resp); }.bind(this)) 

The final code is:

 $(function() { var _ = { initJquery: function() { $('#one').on('click', function() { this.getAjax(); }.bind(this)); }, initJs: function() { $('#two')[0].addEventListener('click', this.getAjax.bind(this)); }, setText: function(text) { $('.update').html(text); }, getAjax: function() { $.ajax({ url: 'txt.txt', type: 'POST', dataType: 'text' }) .done(function(resp) { console.log('this'); console.log(this); this.setText(resp); }.bind(this)) .fail(function() { console.log("error ajax"); }.bind(this)); } }; _.initJquery(); _.initJs(); }); 

Reported as a duplicate by Grundy members, aleksandr barakin , PashaPash ♦ Jun 26 '16 at 7:37 .

A similar question was asked earlier and an answer has already been received. If the answers provided are not exhaustive, please ask a new question .

  • one
    this.getAjax.bind (this) - zhenyab
  • And more specifically, $ ('# two') [0] .addEventListener ('click', this.getAjax.bind (this)); In general, this is of course a matter of style and conventions of the project, but personally I try to write as much as possible bind and switch functions and as little as possible me / self / that. - Duck Learns to Take Cover
  • Bind is useful, but its use is not always possible and justified. On good, the chosen architecture of a code in this case - not successful. There would be simple functions to register, and call them when necessary. - zhenyab
  • @zhenyab seems to me bind / meselfthat - purely a matter of agreement. I have written several projects on ext and several on backbone-based frameworks. In ext, they wrote me / self / that everywhere, bind everywhere in the backbone. This time. Secondly, in the chosen example there is no architecture, it is obviously the minimal reproducible example, artificial. - Duck Learns to Take Cover
  • I will not raise controversy about bind, and in the example there is a certain pattern (how would I say it is more beautiful in Russian?) I would replace the overall pattern :) - zhenyab

1 answer 1

Briefly:

  $('#two')[0].addEventListener('click', this.getAjax.bind(this)); 

Why doesn't it work for you?
As I tried to explain here quite recently , the function exists by itself, without an object attached to it. The callback is passed to the function itself, as an independent entity. Information about what to associate with it is not transmitted. What is to the left of the point serves only to find this function. And this , just means some object, by which method we consider the function, therefore it becomes undefined (or window in lax mode).

What to do?
Passing a callback is not just a function, but a function and context. For this, the bind method is usually used, which creates a wrapper for the function we need with an associated context. When we call this wrapper, it calls your method with a context that it does.

In general, wherever you save the context via var that = this you can save it via bind . This is a matter of agreement in a particular project, but personally I prefer it that way. And in some places it is generally more convenient to use es6 arrow functions that do not create their own separate this .

Your first function with bind

 initJquery: function() { $('#one').on('click', function() { this.getAjax(); }.bind(this)); } 

She (almost) with arrows:

 initJquery: function() { $('#one').on('click', () => this.getAjax()); } 
  • arrow functions are not yet supported everywhere, so it’s better not to use them yet, or to use compiled collectors - Vasily Barbashev
  • yes, that's why I won't touch the arrows yet. (not yet supported everywhere) - Jean-Claude
  • @ Jean-Claude, if you have some kind of assembly, then the transpiler is added to it elementarily - Duck Learns to Take Cover
  • @ Duck not until I can do this The resulting code has the form jsbin.com/kojefilaxi/edit?html,output but without var that = this; it does not work, how to remove that in getAjax ()? - Jean-Claude
  • @ Duck sort of figured out: .done(function() { this.setText(resp); }.bind(this)) - Jean-Claude