Bibliotecas via Closures em JavaScript
Frequentemente em JavaScript, são criadas bibliotecas, que representam conjuntos de funções para uso por outros programadores.
Essas bibliotecas geralmente são encapsuladas em módulos via closures. Isso é feito para que, ao conectar a biblioteca, o menor número possível de funções seja exposto no escopo global.
Geralmente, cada biblioteca se esforça para criar apenas uma variável no escopo global - um objeto com as funções da biblioteca. Ao mesmo tempo, dentro do código da biblioteca, algumas funções são principais e outras são auxiliares. Obviamente, queremos exportar para o escopo global apenas as funções necessárias, sem poluir o objeto exportado com funções auxiliares.
Vamos ver um exemplo. Suponha que temos o seguinte conjunto de funções que gostaríamos de transformar em uma biblioteca:
function square(num) {
return num ** 2;
}
function cube(num) {
return num ** 3;
}
function avg(arr) {
return sum(arr, 1) / arr.length;
}
function digitsSum(num) {
return sum(String(num).split(''));
}
// função auxiliar
function sum(arr) {
let res = 0;
for (let elem of arr) {
res += +elem;
}
return res;
}
Vamos organizar nossas funções na forma de um módulo:
;(function() {
function square(num) {
return num ** 2;
}
function cube(num) {
return num ** 3;
}
function avg(arr) {
return sum(arr, 1) / arr.length;
}
function digitsSum(num) {
return sum(String(num).split(''));
}
// função auxiliar
function sum(arr) {
let res = 0;
for (let elem of arr) {
res += +elem;
}
return res;
}
})();
E agora vamos exportar todas as funções, exceto a auxiliar:
;(function() {
function square(num) {
return num ** 2;
}
function cube(num) {
return num ** 3;
}
function avg(arr) {
return sum(arr, 1) / arr.length;
}
function digitsSum(num) {
return sum(String(num).split(''));
}
// função auxiliar
function sum(arr) {
let res = 0;
for (let elem of arr) {
res += +elem;
}
return res;
}
window.math = {square, cube, avg, digitsSum};
})();
Suponha que temos uma página HTML index.html:
<html>
<head>
<script>
</script>
</head>
</html>
Vamos conectar nossa biblioteca a ela:
<html>
<head>
<script src="math.js"></script>
<script>
</script>
</head>
</html>
Vamos usar as funções da nossa biblioteca:
<html>
<head>
<script src="math.js"></script>
<script>
alert(math.avg([1, 2, 3]) + math.square());
</script>
</head>
</html>
Dado o seguinte código:
function avg1(arr) {
return sum(arr, 1) / arr.length;
}
function avg2(arr) {
return sum(arr, 2) / arr.length;
}
function avg3(arr) {
return sum(arr, 3) / arr.length;
}
// função auxiliar
function sum(arr, pow) {
let res = 0;
for (let elem of arr) {
res += elem ** pow;
}
return res;
}
Organize este código na forma de um módulo. Exporte todas as funções, exceto a auxiliar.
Estude a biblioteca underscore.
Crie sua própria biblioteca similar, replicando
5 a 10 funções da biblioteca
original.