JavaScript: A função da palavra chave “this” e os métodos call, apply e bind

Este post foi escrito como parte de uma série de estudos (resumos) que estou fazendo sobre JavaScript, por isso foi imensamente inspirado na documentação oficial, o que explica muitas similaridades entre os textos. Mas é possível também encontrar aqui alguns pequenos pontos que aprendi que não estão no texto original.
Texto original: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Operators/this

Em JavaScript o this tem um comportamento um pouco diferente das outras linguagens. Seu valor na maioria dos casos depende muito de como uma função é chamada, podendo assim ter seu valor trocado (bem estranho isso), mas é assim mesmo que ele funciona, o que confere muitos poderes para quem está utilizando e com grandes poderes vem grandes bugs :)

Sintaxe:

Em Contexto Global

Em um contexto global a palavra chave this tem o mesmo valor do objeto global (window):

O exemplo acima nos mostra que this é igual a window no contexto global

Em Contexto de função

Dentro de uma função o valor do this depende de como ela é chamada. Vamos aos cenários possíveis.

Para funções declaradas no escopo global:

Neste cenário o valor de this é sempre igual a window:

Mas se utilizamos o modo estrito no contexto da função, o valor de this neste caso será undefined, isso acontece porque neste modo, precisamos explicitamente especificar “quem” chamou a função. Por ex:

Para funções arrow

Nas funções arrow o this é definido pelo contexto ao qual está inserido, mesmo se chamado utilizando os métodos call, apply ou bind.

Como visto no exemplo acima, não importa o que se faça, o valor de this será sempre “window” para este cenário, pois a arrow function foi definida no escopo global.

Se tivéssemos definido a arrow function dentro de uma outra função, como abaixo:

O valor de this neste caso será referenciado ao contexto da função Pessoa.
IMPORTANTE: Interessante também demonstrar que SEM a arrow function o valor de this seria diferente, por ex:

Isto acontece porque antes das arrow functions, toda nova função definia seu próprio valor de this (um novo objeto no caso de um construtor, undefined em chamadas de funções com strict mode, o objeto de contexto se a função é chamada como um “método de objeto”, etc.). Este comportamento é importuno com um estilo de programação orientado a objeto.

Explicação retirada de: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Como método de um objeto

Para funções (métodos) de objetos, o valor do this faz referencia ao próprio objeto no qual se originou a chamada.

No exemplo acima o this faz referencia ao próprio objeto “obj”.

Interessante lembrar que independente de onde a função foi definida e que se ela for referenciada para dentro de um objeto, o resultado será o mesmo. por ex:

Como visto acima a função independent foi definida primariamente fora do objeto ”obj” e referenciada logo após para a propriedade “obj.f” e no final obtivemos o mesmo resultado.

É importante lembrar também que o this se refere sempre ao membro mais imediato, como no exemplo abaixo:

this neste caso se refere ao objeto “b”, por isso retornou 42.

Na cadeia de protótipos (prototype chain) do objeto

Neste caso, o this sempre assume o valor da “instância” que fez por sua vez referencia ao objeto original.

Como visto no exemplo acima “p” é uma instância de “o” e por isso this se refere a “p”  

Em construtores

Quando uma função é usada como um construtor por intermédio da palavra new, o this vai se referir ao novo objeto criado (nova instancia).

Métodos call, apply e bind

Toda função que possui a palavra this dentro de seu corpo, pode usar um dos três métodos.

O this nos manipuladores de eventos no DOM

Para funções utilizadas como manipuladores de eventos, o this se refere sempre ao objeto no qual registrou o evento.

 

  

Migrando do Django 1.10 para o Django 1.11.8

Bora lá então:

Primeiro erro:

Se você está usando uma versão um pouco antiga de django-filter, o erro abaixo pode acontecer:

Django 1.11 compatibility issue – cannot import name flatatt

Para corrigi-lo, basta instalar a ultima versão.

Fonte: https://github.com/carltongibson/django-filter/issues/673

Segundo Erro:

context must be a dict rather than Context.

Basta remover a Classe Context

Ficando assim:

Referencia: https://stackoverflow.com/questions/43787700/django-1-11-typeerror-context-must-be-a-dict-rather-than-context

Terceiro Erro:

Se você está usando django-widget-tweaks e estiver mudando o tipo do campo em um formulário, como no exemplo abaixo:

apenas attr:"type:hidden" não irá funcionar, a explicação para isso está neste link: https://github.com/jazzband/django-widget-tweaks/issues/52

Então para corrigir isso será necessário mudar o tipo do campo no próprio form, dessa forma:

Outras maneiras de mudar o tipo do campo: http://nanvel.name/2014/03/django-change-modelform-widget

Quarto Erro: 

Incompatibilidade de Pickled Objects

1 – Pickled model instance’s Django version 1.10 does not match the current version 1.11.8.
2 - Pickled queryset instance’s Django version 1.10 does not match the current version 1.11.8.

Para corrigir este erro será necessário limpar o seu sistema de cache, seja ele, Redis, Memcached, etc

Fonte: https://docs.djangoproject.com/en/2.0/howto/upgrade-version/#deployment

Quinto Erro:

Se você está usando django-select2, abaixo da versão 5.11.1, o erro build_attrs() takes at most 2 arguments (3 given), pode acontecer:

Para corrigir este erro, atualize o versão para 5.11.1 (obs: a versão 6.0.0 dá suporte apenas para Django 2.0 e Python >= 3.6)

Após esta atualização, o seguinte erro também pode acontecer:

ModelSelect2Widget is missing a QuerySet. Define ModelSelect2Widget.model, ModelSelect2Widget.queryset, or override ModelSelect2Widget.get_queryset().

Para corrigir isso, coloque o parametro model ou queryset no widget, como abaixo:

Sexto Erro:

Não teve sexto erro, aeeeeee, uuuuuuufaa, achei que ia ter mais, por isso comecei a escrever este post, pois quando migramos do Django 1.6 para o Django 1.10, milhões de erros surgiram, para conferir veja este link, http://www.mateuspaduaweb.com.br/atualizando-django-1-6-para-1-9-ou-1-10/.
Que bom que os erros pararam por aqui :)

 

Atualizar (sincronizar) um repositório ‘forkado’ a partir do repositório original

Para sincronizar um repositório que você ‘forkou‘ com seu repositório de origem, primeiro precisamos adicionar ao seu GIT local um caminho que aponte para o repositório original:

Primeiro:
Vamos listar nossos repositórios remotos, vinculados a nossas branches locais.

Segundo:
Vamos adicionar um apontamento para o repositório original:

Terceiro:
Listando novamente os repositórios remotos:

Quarto:
(Fetching)
Descendo o repositório original para sua máquina:

Quinto:
Agora nós temos as branches e as tags do repositório original na nossa máquina

Sexto:
Com o código do repositório original na nossa máquina vamos rodar um comando para ver o que será atualizado em nossa branch master antes de fazer o merge.

Dica: sem o –stat acima você consegue ver todo o código que será atualizado, linha por linha.

Sétimo:
Vamos agora fazer o merge com a master local

Feito !!!
Com isso nosso fork está sincronizado com sua origem.

Fontes:
http://digitaldrummerj.me/git-syncing-fork-with-original-repo/
https://stackoverflow.com/questions/7244321/how-do-i-update-a-github-forked-repository
https://gist.github.com/CristinaSolana/1885435