Why with arrow functions is the context different from a common function?

3

In the snippet I prepared below, I have a table with some simple data. Below the table, there are two labels that account for the total age of the data in the table. The first label is calculated using a common anonymous function, the second one is using an arrow function.

I noticed that in the arrow function, this is Window , not the object that called the function, as in the other case. Because of this, the sum in the label results in NaN (Not a Number)

By reading the documentation , I came up with the concept of this lexicon, but from that point I do not understand anything else. How could I circumvent the situation so that arrow function works the way I expected it to be?

window.onload = function (){
  atualizaSomaIdades();
  atualizaSomaIdadesArrowFunction();
}

$('.excluir').click(function (){
  $(this).parent().parent().remove();
  atualizaSomaIdades();
  atualizaSomaIdadesArrowFunction();
});

function atualizaSomaIdades(){
  var total = 0;
  var rows = $('table').find('tbody').find('tr');
  rows.each(function () {
      total += parseInt($(this).find('td').eq(1).text());
  });
  $('#idade-comum').text(total);
}

function atualizaSomaIdadesArrowFunction(){
  var total = 0;
  var rows = $('table').find('tbody').find('tr');
  rows.each(() => {
    total += parseInt($(this).find('td').eq(1).text());
  });
  $('#idade-arrow-function').text(total);

}
td{
  border: 1px solid black;
}

.negrito{
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><table><thead><tr><td>Nome</td><td>Idade</td><td>Ações</td></tr></thead><tbody><tr><td>João</td><td>25</td><td><buttonclass="excluir">Remover</button>
    </td>
  </tr>
  <tr>
    <td>
      Carlos
    </td>
    <td>
      16
    </td>
    <td>
      <button class="excluir">Remover</button>
    </td>
  </tr>
  <tr>
    <td>
      Artur
    </td>
    <td>
      21
    </td>
    <td>
      <button class="excluir">Remover</button>
    </td>
  </tr>
</tbody>
</table>

<span class="negrito">Total de idade:</span>
<span id="idade-comum"></span>
<span id="idade-arrow-function"></span>
    
asked by anonymous 12.12.2017 / 13:21

3 answers

1

The% void% in the arrow function is very useful when working object-oriented in javascript (with classes for example). The MDN example is very practical:

function Pessoa(){
  this.idade = 0;

  setInterval(() => {
    this.idade++; // |this| corretamente referência ao objeto Pessoa
  }, 1000);
}

var p = new Pessoa();

For your case, so that this does not take a more global context but rather the location of the function, you can indicate the element by changing it:

rows.each((index,elemento) => {

Example

window.onload = function (){
  atualizaSomaIdades();
  atualizaSomaIdadesArrowFunction();
}

$('.excluir').click(function (){
  $(this).parent().parent().remove();
  atualizaSomaIdades();
  atualizaSomaIdadesArrowFunction();
});

function atualizaSomaIdades(){
  var total = 0;
  var rows = $('table').find('tbody').find('tr');
  rows.each(function () {
      total += parseInt($(this).find('td').eq(1).text());
  });
  $('#idade-comum').text(total);
}

function atualizaSomaIdadesArrowFunction(){
  var total = 0;
  var rows = $('table').find('tbody').find('tr');
  rows.each((index,elemento) => {
    total += parseInt($(elemento).find('td').eq(1).text());
  });
  $('#idade-arrow-function').text(total);

}
td{
  border: 1px solid black;
}

.negrito{
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><table><thead><tr><td>Nome</td><td>Idade</td><td>Ações</td></tr></thead><tbody><tr><td>João</td><td>25</td><td><buttonclass="excluir">Remover</button>
    </td>
  </tr>
  <tr>
    <td>
      Carlos
    </td>
    <td>
      16
    </td>
    <td>
      <button class="excluir">Remover</button>
    </td>
  </tr>
  <tr>
    <td>
      Artur
    </td>
    <td>
      21
    </td>
    <td>
      <button class="excluir">Remover</button>
    </td>
  </tr>
</tbody>
</table>

<span class="negrito">Total de idade:</span>
<span id="idade-comum"></span>
<span id="idade-arrow-function"></span>
    
12.12.2017 / 13:42
0

Adding to previous responses, you can use the bind method to determine the context of this for functions:

rows.each((() => { total += parseInt($(this).find('td').eq(1).text()); }).bind(this));

Doc in Mozilla

The bind method receives as its first argument an object called thisArg , which is the context for this calls within this function. Thus, putting .bind(this) in an arrow function causes all this internal to be equal to the this external of the scope of that function.

    
10.01.2018 / 17:11
0

You should use the closures concept to get a direct reference to this of the external context to your arrow function.

Just capture the this into a variable and use that variable inside the arrow function.

const self = this
rows.each(() => {
  total += parseInt($(self).find('td').eq(1).text());
});

Or you can use a function fault%, which you yourself saw that captures this automatically.

If you wanted to learn more about closures:

link

    
12.12.2017 / 13:37