• Nenhum resultado encontrado

Onde usar WeakMaps?

42 6.3 ADMINISTRANDO UMA BIBLIOTECA

CAPÍTULO 7

Às vezes, necessitamos tratar coleções de itens únicos, ou seja, itens que não repetem. Estes itens podem ser qualquer coisa: números, strings, objetos ou mesmo funções. Na prática, isso significa que precisamos criar listas em que só podemos adicionar um item específico uma única vez. Se tentarmos adicioná-lo mais de uma vez, ela deve ser inteligente o suficiente para saber que aquele item já está lá e não o adicionar novamente.

No JavaScript na versão ES5, não temos uma implementação nativa deste tipo de estrutura com essa inteligência. Esta estrutura é chamada de Set e já está presente em diversas linguagens.

Como não temos o Set , para resolver nossos problemas, precisamos criar nossa própria implementação. Temos de ter algum jeito de saber se um dado elemento já está na lista toda vez que adicionamos algo nela. Como tudo no mundo da programação, existem inúmeras formas de se fazer isso. Uma das maneiras imediatas é utilizando o método indexOf toda vez que precisamos adicionar um elemento na lista, para verificar se o elemento já existe nela.

Para contextualizar este exemplo, pense que estamos implementando um sistema online de loteria. Neste sistema, os usuários podem fazer o seu jogo eletronicamente da Mega-Sena,

LISTAS SEM REPETIÇÕES

COM SETS E WEAKSETS

Lotofácil, Quina, Lotomania e outros jogos. Em todos eles, o jogador insere em quais números ele quer apostar. Como os números não podem se repetir em nenhum dos jogos, podemos usar um Set para garantir isto.

Figura 7.1: O Set como nosso aliado para evitar repetições

Primeiro, iniciamos nossa implementação criando um método chamado add que será responsável por adicionar itens na lista. Neste objeto que estamos criando, utilizamos então uma estrutura de Array interna que armazenará todos os valores que vamos inserir.

No método add , usamos esta estrutura interna para fazer a chamada do indexOf que busca pelo objeto alvo dentro no nosso Set . Se a função retorna o valor -1 , significa que não existe nenhuma instância do objeto que queremos adicionar na nossa coleção, logo, podemos adicionar. Caso contrário, não. Veja a implementação deste algoritmo:

function Set() { var array = [];

this.add = function(valor) {

if(array.indexOf(valor) === -1) { array.push(valor); } } } 44 7 LISTAS SEM REPETIÇÕES COM SETS E WEAKSETS

implementada nativamente no JavaScript. Essa implementação já contém todos os métodos que sugerimos anteriormente e muito mais. Além disso, análogo ao WeakMap , também temos o WeakSet . Vamos ver com detalhes como estas estruturas funcionam.

O Set é uma estrutura de dados que nos permite ter listas com valores que nunca se duplicam e que mantém a ordem de inserção dos seus itens. Podemos trocar a implementação que fizemos no tópico anterior para usar a nova implementação nativa do JavaScript ES6.

O código fica basicamente o mesmo, com a diferença do método mostrarValores , que não existe na implementação nativa. Por isso, vamos remover este método e usar uma simples iteração por laço for...of para ver seus valores. Como o Set também é um objeto iterável, isso não é problema:

var set = new Set(); set.add(2);

set.add(1); set.add(2);

for (const valor of set) { console.log(valor); // 2, 1 }

O construtor do Set nos permite passar quais valores queremos com que ele seja inicializado. Para isso, basta passar os valores desejados dentro de um Array . Usando este construtor, já somos capazes de eliminar algumas linhas de código, veja:

var set = new Set([2,1,2]);

for (const valor of set) { console.log(valor); // 2, 1 }

7.1 SET

Repare em um detalhe interessante. Mesmo colocando propositalmente o valor 2 (dois) duplicadamente na lista, o Set se encarregou de se livrar da cópia, mesmo sem dar nenhum indício disto para nós. Isso é uma mão na roda para quando precisamos lidar, por exemplo, com entradas do usuário no sistema, onde é tudo imprevisível.

Para mostrar as demais operações possíveis com Set , usaremos mais um sistema hipotético. Imagine agora que trabalhamos em uma empresa responsável por um sistema de streaming de músicas corrente ao Spotify, mas que tem uma particularidade bem interessante: é focado para programadores. Um serviço de streamimg de músicas para programadores.

Uma das features mais bacanas deste sistema é a criação de listas de músicas personalizadas. O usuário é livre para adicionar as músicas que ele quiser na lista, no entanto, ela só pode ser incluída uma única vez em cada lista.

Figura 7.2: Interface do serviço de música para programadores

Para lidar com todas as operações de lista de músicas no sistema, utilizaremos os métodos que o Set nos oferece. Para facilitar o entendimento dos nossos exemplos, vamos representar as nossas músicas somente pelo seu título. Faremos uma demonstração com

objetos literais mais complexos mais à frente.

Para adicionar uma música a lista personalizada do usuário, usamos o método add visto no exemplo anterior. Este método aceita apenas um parâmetro: o objeto que pretendemos inserir no Set .

var musicas = new Set(); musicas.add('musica1');

for(var musica of musicas) { console.log(musica); // musica1 }

Assim como oferecemos a opção de adicionar uma música, também precisamos oferecer a opção de deletar uma música da lista. Para isso, usamos o método delete . Este aceita como parâmetro o elemento que queremos remover da lista. Caso este elemento não esteja na lista, nada acontece:

var musicas = new Set(['musica1','musica2']); musicas.delete('musica1');

for(var musica of musicas) { console.log(musica); // musica2 }

Mas se o usuário quiser deletar todas as músicas da sua lista de uma vez só, podemos criar um botão que faça isso utilizando o método clear . Este método remove todos os itens do nosso Set , deixando-o inteiramente vazio:

var musicas = new Set([

'musica1','musica2', 'musica3' ]);

musicas.clear();

for(var musica of musicas) { console.log(musica); // nada }

estar em alerta para o fato de que o coletor funciona de forma diferente em cada navegador e não pode ser forçado. Como ele não pode ser forçado, precisamos que ele aja por conta própria.

Assim, precisamos fazer a demonstração em duas partes. Primeiro, vamos remover a referência da música atribuindo o valor null a ela. var musica1 = { titulo: 'O amor não tem rollback', autor: 'SQL' }

var musicas = new Set([musica1]);

console.log(musicas); musica1 = null;

Se fizemos o console.log(musicas) logo de imediato, é possível que não tenha dado tempo para o coletor ter identificado a referência nula e ter removido o musica1 . Isso significa que a lista ainda estará guardando a referência para o objeto que não existe mais. Por isso, aguarde alguns poucos segundos, e então execute o console.log :

console.log(musicas); // {}

Note que a lista se atualizou "automaticamente". O WeakSet verifica quais dos seus elementos não possui mais nenhuma referência válida, e então o remove.

Este é o poder do WeakSet . Há poucas circunstâncias nas quais ele poderá ser útil no dia a dia. Existem muitas discussões em fóruns e blogs de desenvolvimento sobre as possíveis utilidades da estrutura de WeakSet . Um dos casos de uso mais interessante é o de garantir que certo método ou propriedade pertence a um objeto específico e não a todas as instâncias do mesmo tipo. Mas no uso geral, sempre que você tiver preocupação com vazamento de memória, o WeakSet estará a seu dispor.

CAPÍTULO 8

Uma das primeiras coisas que aprendemos quando estudamos JavaScript é que ela é uma linguagem fracamente tipada, ao contrário de linguagens como C++, Cobol, Fortran e Java, que são fortemente tipadas. Na prática, isso siginifica que as variáveis não têm nenhum tipo predeterminado. Em vez disso, o seu tipo foi definido pelo seu valor.

Para definir qualquer tipo de variável no JavaScript, utilizamos a palavra reservada var . Elas podem ser objetos literais, números, caracteres, strings, listas ou funções:

// exemplos

var objeto = {}; // objeto

var numero = 1; // numero

var nome = "Chaves"; // string

var lista = [1,2,3]; // lista

DECLARAÇÃO DE

VARIÁVEIS COM CONST E

Documentos relacionados