Javascript – o método call() e apply()

Todas as funções do javascript possuem alguns métodos como toString(), call() e apply(). Antes de explicar o método function.call() vou exemplificar o funcionamento das funções e escopos, que acredito que isso facilite o entendimento.

Exemplo de código:

var url = 'andafter.org';
function f(){
    console.log(this);
    console.log(this.url);
}
f();

Nesse código eu seto uma variável global url, e quando chamo a função f dou um log em "this" (é a window), então quando chamo this.url o retorno é a variável instanciada fora da função.

O método call()

O método function.call() permite você dizer em qual escopo (essa é a nomenclatura certa? comentem suas opiniões) uma função deve ser executada.

Voltando ao exemplo de código anterior:

var url = 'andafter.org';
var site = { url : 'odesenvolvedor.com.br' };
function f(){
    console.log(this.url);
}
f.call(site);

O function.call() define o que será o "this" dentro da função, e este deve ser passado como parâmetro para o método call.

 

Método call com parâmetros

No exemplo anterior não fizemos uso de parâmetros, apenas do "this". Mas o método call pode receber a partir do segundo parâmeto (o primeiro sempre será o escopo que será atribuído ao this) os parâmetros que serão passados para a função.

var url = 'andafter.org';
var site = { url : 'odesenvolvedor.com.br' };
function f(p1, p2){
    console.log(this.url + ' - ' + p1 + ' - ' + p2);
}
f('aprendendo javascript', 'no andafter!');
f.call(site, 'estudando códigos', 'no desenvolvedor');

O método function.apply()

O método function.apply() tem o mesmo funcionamento do function.call() com uma diferença na forma dos parâmetros, o segundo parâmetro sempre deverá ser um array, contendo todos os parâmetros que serão enviados para a função.

O primeiro parâmetro continua sendo o escopo onde sua função será executada.

var url = 'andafter.org';
var site = { url : 'odesenvolvedor.com.br' };
function f(p1, p2){
    console.log(this.url + ' - ' + p1 + ' ' + p2);
}
f('aprendendo javascript', 'no andafter!');
f.apply(site, ['estudando códigos', 'no desenvolvedor']);

Agora você já sabe como definir em qual escopo uma função será executada, e também tem um facilitador para funções que chamam funções.

Este é um post introdutório para alguns códigos mais complexos que virão, quase todos resultados das minhas pesquisas de performance de javascript e desenvolvimento de bibliotecas como o jQuery Lazy Load.

Javascript: como alterar o intervalo de um timeout?

Estou estudando NodeJS (veja como instalar o NodeJS no Ubuntu) e meu interesse por javascript aumentou com isso – comecei projetos para estudar desenvolvimento de games em javascript.  Nesses estudos percebi que o  setInterval e setTimeout são grandes ferramentas para a criação de scripts complexos, mas que são pouco explorados normalmente. 

Como alterar o interval no Javascript?

Supondo que você instanciou uma função para ser executada 10 segundos depois que o usuário entrar na página (setTimeout). Mas caso o usuário clique no botão Y esta função tem que ter um novo delay, novamente de 10 segundos.

Não encontrei uma maneira de alterar um timeout ou interval em andamento, então a lógica é cancelar o timer que está em funcionamento e setar um novo timer, com o intervalo desejado.

Vamos por partes, cancelando a função já instanciada.

 

Como cancelar um setTimeout em javascript

Nosso código:

var agendamento = setTimeout(function(){
 console.log('ação agendada!');
}, 1000);

/* Cancela o agendamento */
clearTimeout(agendamento);

Simples assim! 

Alterando o intervalo com ação do usuário

var agendamento = setTimeout(function(){
 console.log('ação agendada!');
}, 1000);

$('a.cancela').click(function(){
 clearTimeout(agendamento);
 var agendamento = setTimeout(function(){
  console.log('ação agendada!');
 }, 1000);
});

 

Poderia melhorar o código transformando a criação do agendamento em uma função, mas optei por deixar o mais legível para facilitar o entendimento.

Tem alguma forma diferente de fazer isso? Deixe um comentário!

O que é browser reflow?

Com o crescimento da banda larga e a evolução da web como um todo, a preocupação de performance deixou de ser exclusividades dos desenvolvedores back-end e se tornou uma grande preocupação de front-end.

Essas preocupações me levaram a melhorar muito meu código javascript (vejas estas dicas de performance em javascript) e aqui no iG comecei a estudar melhor a forma que os navegadores trabalham a fim de melhorar a performance desde a parte do HTML.

O que é browser reflow?

O "browser reflow" é uma tarefa do navegador que calcula o posicionamento e dimensão de todos os elementos da sua página. O navegador percorre toda a árvore DOM mesclando a estrutura do HTML com o CSS (externou ou inline) que fica na "style structure", isso forma a Render Tree, que é o que nós visualizamos.

A cada reflow, todos os elementos tem o tamanho e reposição calculadas, por isso que um excesso de reflow causa mais processamento e consequentemente páginas com uma renderização mais demorada.

Para entender melhor o que é um reflow, assista o vídeo de como o navegador renderiza o HTML, neste mesmo post.

O que é um repaint?

Repaint é quando acontece uma alteração visual no elemento (cor, background) que não altera suas dimensões (margem, padding, largura ou altura). O repaint é menos custoso em termos de processamento.

 

Minimzando o browser reflow

Agora que você já sabe o que é reflow e sabe o impacto na performance da exibição da página, a redução do desse processamento se torna mais importante para saber como fazer páginas rápidas.

O Google tem um vídeo bacana (em inglês) com algumas dicas para minimizar o reflow:

Dicas para manter suas páginas mais rápidas

  • Minimize o browser reflow
  • Reduza o HTML desnecessário do DOM e tente manter a árvore o mais "raza" possível. Quando uma alteração é feita em algum elemento ele causa efeitos em toda a árvode DOM, quando menos profunda ela for mais rápido será o reflow e qualquer outra manipulação no DOM.
  • Minimize o CSS e remova CSS que não é utilizado – o CSS é "interpretado" para formação da render tree, e o CSS "sobrando" sem dúvida vai tornar a render tree mais lenta, refletindo diretamente na experiência do usuário ao navegar nas suas páginas.
  • Para fazer animações e layouts mais complexos, sempre que possível faça isso fora do "reflow", para isso utilize posição absoluta ou fixed.
  • Evite seletores de CSS complexos, quanto mais profundo e complexo for um seletor mais custoso em performance será para mondar a render tree da página.

 

Como o browser renderiza sua página?

Para exemplificar melhor os assuntos que tratamos, abaixo tem um vídeo da Mozzilla, que mostra como o browser trabalha para renderizar uma página.

Não deixe de ver a apresentação sobre performance em javascript, outro fator muito importante quando falamos de performance no front-end.

Vamos fazer uma web mais rápida? 🙂

Referências:

Googl e code

Tableless

Como instalar o NodeJS v0.4.x no Ubuntu 11.10

Primeira Segunda-Feira de 2012 e o campeão aqui toma uma importante decisão: atualizar o Ubuntu no computador do trabalho. Instalei a versão 11.10 e tudo funcionou melhor do que o esperado. Não tinha feito a atualização até agora com medo da performance do Unity, e de problemas de compatibilidade com placa de vídeo.

Se você não precisa de uma versão antiga do NodeJS recomendo que você leia este tutorial de como instalar o NodeJS e npm no Ubuntu

O Ubuntu atualizou uma série de pacotes, dentre ele algumas dependências do NodeJS (e talvez até o próprio node, não tenho certeza). Para rodar o sistema que trabalho aqui no iG, preciso do NodeJS e descobri que devido aos pacotes do npm (nodeJS e npm são cheios de dependências) era necessário a versão antiga do NodeJS (sabia que a 4.7 e 4.8 funcionavam).

Instalando o nodeJS 4.x no Ubuntu 11.10

Depois de quase 2 dias quebrando a cabeça, segue um tutorial do que eu fiz para instalar a versão antiga do nodejs.

O bug

Tentei fazer a instalação normalmente, e descobri que com as últimas versões da biblioteca openssl (o Ubuntu 11 pega essas versões) as versões antigas do NodeJS (4.x) não compilam, pois o openssl parou de dar suporte a não-sei-o-que que o NodeJS utilizava.

 

A solução

Depois de um dia inteiro tentando rodar o sistema na última versão do NodeJS (6) ou tentando instalar a versão antiga, finalmente cheguei na conclusão acima, então a solução era óbvia, você precisa:

  1. Instalar uma versão antiga do openssl (consegui compilar a versão 4.7 do NodeJS com a OpenSSL 1.0.0a)
  2. Instalar a versão desejada do NodeJS (4.7 no meu caso)
  3. Instalar a versão antiga do npm (2.0)

Forçando o Curtir do javascript com injection de JS

Devido ao lançamento do novo Arena (tá sensacional, quem curte games deveria conferir e escutar o Games on The Rocks) o @iG está fazendo uma promoção para seus colaboradores, a publicação que tiver mais "curtir" vai levar para casa um XBox neste Natal.

Adendo: eu quero este xbox.

Estou participando (e você deveria me ajudar a ganhar, curtindo esta minha publicação no Facebook), mas aí resolvi brincar um pouco com javascript depois de encher o saco de alguns amigos para eles curtirem a página…

Adendo 2: vou sortear 3 vale presente de R$100,00 do Eu Compraria! entre todos que curtirem a página se eu for o ganhador do XBox

Lembrei da publicação sobre "injection" de javascript em qualquer página, e pensei: porque não agradecer as pessoas divertindo um pouco o "curtir"? 😀

No quesito "vantagem" não há nenhuma, nao é uma forma de forçar a pessoa a curtir pois depende da ação do usuário, mas com o código tem uma surpresinha…

Para funcionar:

1º Certifique-se de que você está logado no Facebook

2º Acesse esta publicação do facebook  em uma nova aba

3º Arraste