Revisão dos Fundamentos de JavaScript

Construtor de String e Método toString()

  • Definição: Um objeto string é usado para representar uma sequência de caracteres. Objetos string são criados usando a função construtora String, que envolve o valor primitivo em um objeto.
const greetingObject = new String("Hello, world!");

console.log(typeof greetingObject); // "object"
  • Método toString(): Este método converte um valor para sua representação em string. É um método que você pode usar para números, booleanos, arrays e objetos.
const num = 10;
console.log(num.toString()); // "10"

const arr = [1, 2, 3];
console.log(arr.toString()); // "1,2,3"
Este método aceita um radix opcional que é um número de 2 a 36. Esse radix representa a base, como base 2 para binário ou base 8 para octal. Se o radix não for especificado, o padrão é base 10, que é decimal.
const num = 10;
console.log(num.toString(2)); // "1010"(binary)

Construtor Number

  • Definição: O construtor Number é usado para criar um objeto número. O objeto número contém algumas propriedades e métodos úteis como os métodos isNaN e toFixed. Na maioria das vezes, você usará o construtor Number para converter outros tipos de dados para o tipo de dado número.
const myNum = new Number("34");
console.log(typeof myNum); // "object"

const num = Number('100');
console.log(num); // 100

console.log(typeof num); // number

Melhores Práticas para Nomear Variáveis e Funções

  • camelCasing: Por convenção, desenvolvedores JavaScript usam camel casing para nomear variáveis e funções. Camel casing é quando a primeira palavra está toda em minúsculas e as palavras seguintes começam com letra maiúscula. Ex. isLoading.
  • Nomeando Booleanos: Para variáveis booleanas, é uma prática comum usar prefixos como "is", "has" ou "can".
let isLoading = true;
let hasPermission = false;
let canEdit = true;
  • Nomeando Funções: Para funções, o nome deve indicar claramente o que a função faz. Para funções que retornam um booleano (frequentemente chamadas de predicados), você pode usar os mesmos prefixos "is", "has" ou "can". Quando você tem funções que recuperam dados, é comum começar com a palavra "get". Quando você tem funções que definem dados, é comum começar com a palavra "set". Para funções manipuladoras de eventos, você pode usar o prefixo "handle" ou o sufixo "Handler".
function getUserData() { /* ... */ }

function isValidEmail(email) { /* ... */ }

function getProductDetails(productId) { /* ... */ }

function setUserPreferences(preferences) { /* ... */ }

function handleClick() { /* ... */ }
  • Nomeando Variáveis Dentro de Loops: Ao nomear variáveis iteradoras em loops, é comum usar letras simples como i, j ou k.
for (let i = 0; i < array.length; i++) { /* ... */ }

Trabalhando com Arrays Esparsos

  • Definition: It is possible to have arrays with empty slots. Slots vazios são definidos como slots que não contêm nada. This is different than array slots with the value of undefined. Esses tipos de arrays são conhecidos como sparse arrays.
const sparseArray = [1, , , 4];
console.log(sparseArray.length); // 4

Linters e Formatters

  • Linters: Um linter é uma ferramenta de análise estática de código que sinaliza erros de programação, bugs, erros de estilo e construções suspeitas. Um exemplo de linter comum seria o ESLint.
  • Formatters: Formatters são ferramentas que formatam automaticamente seu código para aderir a um guia de estilo específico. Um exemplo de formatter comum seria Prettier.

Gerenciamento de Memória

  • Definição: Gerenciamento de memória é o processo de controlar a memória, alocando-a quando necessário e liberando-a quando não é mais necessária. JavaScript usa gerenciamento automático de memória. Isso significa que JavaScript (mais especificamente, o motor JavaScript no seu navegador) cuida da alocação e desalocação de memória para você. Você não precisa liberar explicitamente a memória no seu código. Esse processo automático é frequentemente chamado de "garbage collection."

Closures

  • Definição: Um closure é uma função que tem acesso a variáveis em seu escopo léxico externo (envolvente), mesmo depois que a função externa retornou.
function outerFunction(x) {
  let y = 10;
  function innerFunction() {
    console.log(x + y);
  }
  return innerFunction;
}

let closure = outerFunction(5);
closure(); // 15

Palavra-chave var e Hoisting

  • Definição: var foi a forma original de declarar variáveis antes de 2015. Mas havia alguns problemas que vinham com var em termos de escopo, redeclaração e mais. Por isso é que a programação moderna em JavaScript usa let e const em vez disso.
  • Redefinindo Variáveis com var: Se você tentar redefinir uma variável usando let, você receberá um SyntaxError. Mas com var, é permitido redefinir uma variável.
// Uncaught SyntaxError: Identifier 'num' has already been declared 
let num = 19;
let num = 18;

var myNum = 5;
var myNum = 10; // This is allowed and doesn't throw an error

console.log(myNum) // 10
  • var e Escopo: Variáveis declaradas com var dentro de um bloco (como uma declaração if ou um loop for) ainda são acessíveis fora desse bloco.
if (true) {
  var num = 5;
}
console.log(num); // 5
  • Hoisting: Este é o comportamento padrão do JavaScript de mover declarações para o topo de seus respectivos escopos durante a fase de compilação antes que o código seja executado. Quando você declara uma variável usando a palavra-chave var, o JavaScript eleva a declaração para o topo do seu escopo.
console.log(num); // undefined
var num = 5;
console.log(num); // 5
Quando você declara uma função usando a sintaxe de declaração de função, tanto o nome da função quanto o corpo da função são içados. Isso significa que você pode chamar uma função antes de declará-la no seu código.
sayHello(); // "Hello, World!"

function sayHello() {
  console.log("Hello, World!");
}
Declarações de variáveis feitas com let ou const são içadas, mas não são inicializadas e você não pode acessá-las antes da declaração real no seu código. Esse comportamento é frequentemente referido como a "zona morta temporal".
console.log(num); // Throws a ReferenceError
let num = 10;

Trabalhando com Imports, Exports e Modules

  • Módulo: Esta é uma unidade autônoma de código que encapsula funções, classes ou variáveis relacionadas. Para criar um módulo, você escreve seu código JavaScript em um arquivo separado.
  • Exports: Quaisquer variáveis, funções ou classes que você deseja tornar disponíveis para outras partes da sua aplicação precisam ser explicitamente exportadas usando a palavra-chave export. Existem dois tipos de exportação: named export e default export.
  • Imports: Para usar os itens exportados em outra parte da sua aplicação, você precisa importá-los usando a palavra-chave import. Os tipos podem ser importação nomeada, importação padrão e importação de namespace.
// Within a file called math.js, we export the following functions:

// Named export
export function add(num1, num2) {
  return num1 + num2;
}

// Default export
export default function subtract(num1, num2) {
  return num1 - num2;
}

// Within another file, we can import the functions from math.js.

// Named import - This line imports the add function.
// The name of the function must exactly match the one exported from math.js.
import { add } from './math.js';

// Default import - This line imports the subtract function.
// The name of the function can be anything.
import subtractFunc from './math.js';

// Namespace import - This line imports everything from the file.
import * as Math from './math.js';

console.log(add(5, 3)); // 8
console.log(subtractFunc(5, 3)); // 2
console.log(Math.add(5, 3)); // 8
console.log(Math.subtract(5, 3)); // 2