sábado, 25 de março de 2017

5 formas de se criar objetos no Javascript


O Javascript é uma linguagem orientada a objetos muito flexível. E um dos motivos para isso é seu forte paradigma funcional, tão importante quanto o primeiro. Por conta disso, existe mais de uma forma de criarmos objetos e lidarmos com herança e polimorfismo.

Hoje eu vou mostrar as cinco formas que temos de criarmos objetos em Javascript e as particularidades de cada uma delas.

sábado, 4 de março de 2017

Entenda Closures Finalmente



Hoje vou apresentar um conceito que permeia todo código Javascript. Apesar de aparentar complexo à primeira vista, vemos que ele é bem simples depois que o entendemos.

A primeira coisa que precisamos entender é que toda função em Javascript é uma closure. Isso porque uma closure nada mais é que uma função que guarda uma referência de cada variável definida fora do seu escopo. Veja um exemplo:
var nome = "João",
    idade = 30

function imprimeDados() {
  console.log(nome + " " + idade)
}

imprimeDados()

Mas isso é apenas uma função que acessa varíaveis globais!? Exatamente. Closures não são nada muito além disso. No entanto, uma closure só possui acesso a variáveis declaradas fora do seu escopo, mas não dentro de funções definidas no seu próprio escopo.



Como pode ser visto na imagem, cada closure tem acesso ao seu próprio escopo e a todos os de fora. Mas uma outra característica interessante das closures é a possibilidade de continuar referenciando variáveis de funções que já terminaram. Vamos com mais um exemplo:

Supondo que nós precisássemos de uma função que a cada vez que é executada, retorna um contador incrementado em 1. Como poderiamos fazer isso?

A primeira forma é com uma varíavel global:
var cont = 0

function somaUm () {
  return ++cont
}

somaUm() // 1
somaUm() // 2
somaUm() // 3

O problema com essa solução é que deixamos a variável cont disponível para ser modificada. Colocar a variável dentro da função não funcionaria, pois toda hora ela seria declarada com valor 0. O ideal é que pudéssemos incrementar uma variável que não pode ser acessada de nenhum lugar fora da função. É ai que entra o bom uso de uma closure.

Utilizando funções anônimas imediatamente invocadas junto com uma closure, podemos fazer exatamente o que queremos:
var somaUm = (function () {
  var cont = 0

  return function () {
    return ++cont
  }

})()

somaUm() // 1
somaUm() // 2
somaUm() // 3

Aqui acontecem duas mágicas muito interessantes. Primeiro, criamos uma função anônima que é invocada assim que é criada. Se você não entende bem esse conceito de função imediatamente invocada, dê uma olhada aqui! Essa função retorna uma nova função (que é uma closure), que sempre retorna a variável da função anônima depois de incrementá-la.

Agora perceba que interessante, a variável que a função somaUm incrementa é a variável cont da função anônima que foi executada apenas no início. Dessa forma, apenas a somaUm tem acesso a ela.

Se ela foi executada apenas no início, como essa variável pode ainda continuar existindo? Se sabemos que variáveis locais só existem enquanto a função estiver sendo executada?

Com closures, todas as variáveis que ela referenciou continuam existindo enquanto ela também existir. Todas as variáveis da função anônima que foi executada no início vão continuar na memória do computador enquanto a closure que a referenciou puder ser chamada.

O que esse código faz na prática é criar uma variável privada, semelhante ao uso da keyword private do Java.

Se esse exemplo ainda ficou um pouco obscuro pra você, não se preocupe! Entender completamente esses conceitos no Javascript são um pouco complicados mesmo. Mas a continuidade nos estudos do fundamento da linguagem vai fazer com que você gradualmente se familiarize com todos os conceitos.

Se tiver alguma sugestão ou dúvida, deixe um comentário aqui. Vou ficar muito feliz de saber o que você achou desse artigo.

Ate mais!

sábado, 25 de fevereiro de 2017

Entenda finalmente o this, bind(), call() e apply()


Olá, hoje vou abordar um assunto que pode confundir desenvolvedores que estão vindo de uma linguagem puramente orientada a objetos, para o Javascript a pouco tempo: o uso do this, e algumas funções que tem muito a ver com ele.

terça-feira, 31 de janeiro de 2017

Tudo o que você precisa saber sobre as IIFEs


IIFE é um conceito frequentemente utilizado por desenvolvedores, mesmo que não saibam exatamente como ele funciona ou porque tem que ser feito assim. A explicação é simples de dizer, mas mais difícil de explicar, então iremos por partes.

IIFE é a sigla para Immediately-invoked function expression, que em português seria mais ou menos como Expressão de Função Imediatamente Invocada. Ou seja, é uma função que, assim que criada, é executada.

Ela é utilizada principalmente para evitar o Hoisting dentro de blocos, evitar a poluição de variáveis com escopo global e também para que possamos criar variáveis e funções privadas, com funções públicas para lidar com elas.

Como Funciona?

Para entender melhor esse conceito, primeiro devemos saber que o Javascript diferencia todas as instruções de códigos como expressão (expression) ou declaração (statement). Qualquer código que retorne um resultado é considerado como uma expressão, enquanto que estruturas condicionais ou de repetição são instruções declarativas (statement). Por exemplo:
var a = 1,
    x = 0

if(a > 0) {         // Statement
    x = a + 2       // Expression
}

O if não retorna nenhum resultado, apenas altera o fluxo de execução do programa. Mas, para que ele faça isso, ele precisa validar uma expression. Então, ele espera o resultado dessa expression, para só depois decidir qual caminho o programa deverá tomar. Em resumo, poderíamos dizer que um statement é uma instrução que altera a ordem padrão de execução do código (de cima pra baixo) e uma expression, qualquer instrução que gere um resultado, mesmo que nulo.

E porque é útil saber isso para entender o IIFE? O motivo disso é que dependendo da forma como criamos uma função, o Javascript pode tratá-la como um statement ou uma expression.

E quando uma função é considerada um statement? Justamente quando a declaramos no código, criando-a da forma padrão:
function somaUm(x) {
    return x + 1;
}

Ela é considerada um statement nesse caso porque nós estamos apenas declarando-a para usar depois. Se tentássemos executá-la como abaixo, passando como parâmetro o valor 10, daria um erro:
function somaUm(x) {
    return x + 1;
}(10)

Isso acontece porque executá-la assim seria o mesmo que fazer:
function somaUm(x) {
    return x + 1;
}

(10)  // SyntaxError: Unexpected token )

Perceba inclusive que o erro trata de um ")" colocado no lugar errado, o erro não menciona nada da tentativa de se executar um statement.

E quando uma função é considerada uma expression? Um dos casos é quando vamos invocá-las. A função é uma expression nesse caso pois nesse momento o interpretador realmente espera que ela retorne algum valor, mesmo que isso não aconteça.

Então, para conseguirmos executar uma função assim que a criarmos, é necessário primeiro fazer com que o interpretador pense que ela seja uma expression! E como fazemos isso? Colocando-a entre parênteses.
(function somaUm(x) {
    return x + 1;
})

Isso é possível pois dentro de parênteses só é possível colocarmos expressions. Por isso que o código abaixo nunca poderia funcionar:
(if(1 < 2) console.log("Não funciona"))

Pois o if sempre será considerado como um statement. Quando uma função é tratada como uma expression, ela pode ser executada. E é por isso que uma IIFE funciona.
Depois que a função estiver dentro de parênteses, basta invocá-la, passando o parâmetro que quiser:
(function somaUm(x) {
    return x + 1;
})(10)

Mas se o parênteses obriga que dentro dele exista apenas expressions, os operadores +, -, *, /, !, = e new também. Quando realizamos alguma operação aritmética, é necessário que façamos com pelo menos uma expressão ou dois valores. Não tem como somar 1 + if. Isso quer dizer que, se colocarmos uma função logo depois de um sinal de + por exemplo, ela também será considerada uma expression. É por isso que os códigos abaixo são perfeitamente válidos, apesar de serem menos utilizados:
+function () { console.log("Olá Mundo!")}()
-function () { console.log("Olá Mundo!")}()
*function () { console.log("Olá Mundo!")}()
/function () { console.log("Olá Mundo!")}()
!function () { console.log("Olá Mundo!")}()

var meuNome = function () { return "Thiago" }()

new function () { console.log("Olá Mundo!")}()

Outra coisa que é necessário explicar é que nós podemos criar IIFEs com funções anônimas, que é o mais comum, mas também podemos criá-las com funções nomeadas, conforme mostrei nos exemplos. A grande diferença é que quando criamos IIFEs com funções nomeadas, nós poderemos utilizar o nome para fazer chamadas recursivas, o que já não seria possível com uma função anônima:
var fazerFatorial = function fatorial(x) {
    if (x == 0)
        return 1
    return x * fatorial(x - 1)
}

console.log(fatorial(5))        // fatorial is not defined
console.log(fazerFatorial(5))   // 120

Nesse exemplo de função comum, vemos que o nome que damos à função só pode ser utilizado dentro dela. Fora do escopo devemos utilizar a variável à qual ela foi atribuida. O mesmo aconteceria com uma IIFE.

No próximo artigo, pretendo mostrar como evitar o hoisting de variáveis sem a necessidade de utilizar a técnica IIFE, e alguns outros truques do ECMAScript 2016.

Até mais!

sexta-feira, 27 de janeiro de 2017

Escopo e Hoisting no Javascript



A forma como o javascript lida com o escopo de variáveis e funções pode ser um tanto quanto confusa para quem vem de outras linguagens imperativas como C, Java ou C++. Enquanto nessas linguagens as variáveis possuem um escopo de bloco, no javascript as variáveis possuem escopo de função. Vamos ver um exemplo em C:
int escopo() {
  int idade = 12;

  if(1) {
    int idade = 20;
    int ano = 2017;
  }
    
  printf("%d", idade);
  print("%d", ano);      // error: ‘ano’ undeclared (first use in this function)
}

Que valor você acha que a variável idade terá no momento de escrever o resultado na tela? Se respondeu 12, acertou. Isso acontece no C porque blocos como if, while e for possuem seu próprio escopo dentro da função. A variável idade dentro do if é diferente da variável idade da função main. Já como a variável ano foi criada apenas dentro do bloco if, ela não existe do lado de "fora", e portanto, esse código causaria um erro.

Agora vejamos como esse mesmo código funcionaria no Javascript:
function escopo() {
  var idade = 12;

  if(true) {
    var idade = 20;
    var ano = 2017;
  }
    
  console.log(idade); // 20
  console.log(ano); // 2017
}

Mas como pode ter funcionado? O que acontece é que no javascript blocos como o if, for e while não possuem escopos com variáveis. Todas as variáveis são sempre colocadas dentro do escopo da função. Quando você declara a variável ano por exemplo, ela será válida na função também, pois é onde fica delimitado seu escopo. Com relação à variável idade, você estaria apenas mudando o seu valor.

Mas, como o javascript faz para a função enxergar uma variável dentro de um bloco? Isso é feito por um recurso da linguagem chamado hoisting. Hoisting em inglês quer dizer içar ou erguer com um guindaste, que tem a ver com o que o Javascript realmente faz.

Não importa o lugar onde declaramos uma função ou variável e nem em qual ordem, o Javascript sempre vai movê-la sorrateiramente através do interpretador pro lugar mais alto do seu escopo. Ou seja, nos dois exemplos abaixo, as duas funções são idênticas para o interpretador do Javascript:
function hoisting() {
  var idade = 12
  console.log(idade)

  if(idade > 10) {
    var nome = "Pedro"
    console.log(nome)

    var ano = 2017
    console.log(ano)
  }
}

function hoisting2() {
  var idade, nome, ano

  idade = 12
  console.log(idade)

  if(idade > 10) {
    nome = "Pedro"
    console.log(nome)

    ano = 2017
    console.log(ano)
  }
}

O que o Javascript fez aqui foi mover todas as declarações de variáveis para o ponto mais alto do escopo. É por isso que podemos utilizar variáveis declaradas dentro de blocos no escopo da função. E o mesmo acontece com funções.

No Javascript podemos declarar funções de duas maneiras:
function imprimir() {
  console.log("Olá Mundo")
}

var imprimir = function() {
  console.log("Olá Mundo")
}

No caso de funções declaradas explicitamente, o Javascript irá movê-la inteira para o início do escopo mais próximo. Mas, quando a função é declarada dentro de uma variável, apenas a variável é movida, o que pode causar mais uma confusão. Veja o exemplo:
imprimirAno() // Funciona
imprimirNome() // TypeError: imprimirNome is not a function

function imprimirAno() {
  return 2017
}

var imprimirNome = function() {
  return "Maria"
}

Aqui, a função imprimirAno foi movida inteira para o início do escopo, enquanto que no caso de imprimirNome, apenas a declaração da variável foi movida pra cima. Enquanto a declaração de todas as variáveis são movidas, suas definições só acontecem no momento que o interpretador chega no local de execução do código. O exemplo acima na verdade foi interpretado Javascript assim:
var imprimirNome
function imprimirAno() {
  return 2017
}

imprimirAno()
imprimirNome()

imprimirNome = function() {
  return "Maria"
}

O que muda com let e const

Desde o ECMAScript 6, o javascript passou a ter duas novas maneiras de declarar variáveis. Vou explicar como cada uma delas altera a forma como o javascript trabalha com escopo e hoisting de variáveis e funções:
Veja esse exemplo:
var x = 1;

if(true) {
    let x = 10
}

Que valor você acha que o x terá no momento de mostrar o resultado na tela? Se respondeu 1, acertou!

O que acontece aqui é que variáveis declaradas com o let terão um escopo de bloco, ou seja, a variável será içada (hoisting) até o início do primeiro bloco que encontrar. A partir de agora então, não será mais preciso utilizar a técnica IIFE para isolar uma variável do resto do código.
var a = 10
let b = 20

if(a < 11) {
 var a = 12
 let b = 50

 console.log(a)
 console.log(b)
}

console.log(a)
console.log(b)

Nesse exemplo, apenas a variável a foi alterada quando saiu do bloco, pois com ela o hoisting foi feito com base no escopo de função, enquanto que o b dentro do if deixa de existir assim que o bloco é finalizado.

A próxima keyword inserida no Javascript é interessante pois com ela conseguimos bloquear uma variável de ser redeclarada com outro valor. Veja um exemplo:
const a = 2
const b = "olá"
const c = {x: 1, y: 2}

console.log(a)
console.log(b)
console.log(c)

a++
b = b + "mundo"
c = {x: 3, y: 4)

Depois que definimos um valor pela primeira vez para uma variável declarada com o const, não poderemos redefinir esse valor novamente. Isso é útil pois impede que outras partes do programa utilize essa variável para armazenar outro valor. Note no entanto que, apesar dela bloquear a redefinição de valores, não impede que uma variável que referencia um objeto, tenha o valor de algum de seus atributos alterados. Veja que o exemplo abaixo é perfeitamente possível:
const c = {x: 1, y: 2}

console.log(c) // {x: 1, y: 2}

c.x = 2
c.y = 4

console.log(c) // {x: 2, y: 4}

Para fazer com que um objeto seja completamente imutável, é necessário congelá-lo. Isso pode ser feito com Object.freeze():
const c = {x: 1, y: 2}
Object.freeze(c)

c.x = 100
c.y = 200

console.log(c) // {x: 1, y: 2}

Ainda assim, o Object.freeze() congela apenas o primeiro nível de atributos. Caso exista uma variável que referencie a um objeto, esse objeto não será congelado pelo método. Caso se intesse em utilizar objetos imutáveis, veja a biblioteca Immutable.js. É muito interessante e vale o estudo.

Conhecendo a forma como a linguagem lida com o escopo e o conceito de hoisting, fica muito mais fácil entender problemas que até então pareceriam completamente sem sentido. No entanto, o Javascript também possui um recurso fundamental pra quem deseja se tornar um Jedi: as Closures.

Falarei sobre elas no próximo artigo. Até la!

terça-feira, 24 de janeiro de 2017

A melhor configuração possível do Zsh!

O Zsh é o shell mais poderoso do GNU/Linux. É cheio de funcionalidades e extremamente configurável. Apesar de que configurá-lo não seja tarefa das mais fáceis, já existem várias configurações prontas feitas por várias pessoas mundo. A melhor forma de configurá-lo é utilizando o Oh-My-Zsh, que vou ensinar aqui como fazer.

Além do Zsh, vamos utilizá-lo junto com um terminal rápido e prático chamado Guake. A vantagem do Guake é que ao invés dele abrir em uma nova janela, ele se sobrepõe ao programa que estiver em execução no momento, e você não precisa ficar alternando entre ele e outro programa com Alt + Tab. De onde você estiver, pode abrí-lo e fechá-lo rapidamente apenas apertando F12. Além disso, também é possível criar, renomear e mover novas abas apenas com o teclado.
O resultado final ficará assim:


Vamos começar

1) Precisamos instalar o Zsh antes de iniciar a configuração
sudo aptitude install zsh

2) Agora temos que instalar o git e o curl, que utilizaremos para baixar o Oh-My-Zsh
sudo aptitude install curl git

3) Vamos instalar o Oh-My-Zsh utilizando o Curl
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

4) Só com esses três passos assim você já pode ter um Zsh funcional, mas ele ainda não vai estar tão legal quanto na foto. Para adicionar o suporte ao git e outros plugins é necessário alterar o arquivo ~/.zshrc que fica no diretório do seu usuário.
Existem vários plugins interessantes para adicionar ao Zsh, uma lista mais completa pode ser encontrada aqui.
Depois de escolher, basta procurar a linha plugins no arquivo .zshrc e adicioná-lo lá. Os meus plugins ficaram assim:
plugins=(git mvn node npm sudo vagrant command-not-found ubuntu)

5) Agora é necessário alterar o tema padrão do Zsh, por um tema mais copleto. Entre novamente no arquivo .zshrc e altere a linha:
ZSH_THEME="robbyrussell" troque por ZSH_THEME="agnoster"

6) Esse tema exige algumas fontes e símbolos personalizados para funcionar. Vamos baixá-los agora:

a) Baixar gerenciador de pacotes do python para baixar o powerline. Pacote que contém as fontes.
sudo aptitude install psutils bzr i3 python-pip
pip install --upgrade pip

b) Baixar as fontes
cd ~
wget https://github.com/powerline/powerline/raw/develop/font/PowerlineSymbols.otf
wget https://github.com/powerline/powerline/raw/develop/font/10-powerline-symbols.conf

c) Agora vamos configurar as fontes
mkdir .fonts
mv PowerlineSymbols.otf ~/.fonts/
fc-cache -vf ~/.fonts/
mkdir -p ~/.config/fontconfig/conf.d/
mv 10-powerline-symbols.conf ~/.config/fontconfig/conf.d/
chsh -s /usr/bin/zsh

7) Com as fontes instaladas e configuradas, basta instalar o terminal Guake agora:
sudo aptitude install guake

8) Agora abra as preferências do Guake, pelo menu no Unity ou do Gnome. Vá nas opções Shell → Interpretador padrão e altere para /usr/bin/zsh.

9) Na aba atalhos é possível alterar todos os atalhos padrões do Guake para criar e fechar abas, abrir e fechá-lo.
Os comandos mais utilizados são:

→ F11 => alterna tela cheia
→ CTRL + SHIFT + T => nova aba do Guake
→ CTRL + Page Up => altera para a aba anterior
→ CTRL + Page Down => altera para a próxima aba
→ CTRL + + => Aumenta o tamanho da fonte
→ CTRL + - => Diminui o tamanho da fonte

sábado, 5 de dezembro de 2015