Skip to content

Latest commit

 

History

History
2509 lines (1696 loc) · 68.5 KB

README_pt_BR.md

File metadata and controls

2509 lines (1696 loc) · 68.5 KB

Lista de questões (avançadas) sobre JavaScript

Posto questões de múltipla escolha sobre JavaScript no meu Instagram, as quais também posto aqui!

Do básico ao avançado: Teste quão bem você conhece o JavaScript, refresque um pouco do seu conhecimento, ou se prepare para uma entrevista! 💪 🚀 Eu atualizo esse repositório semanalmente com novas questões.

As respostas estão em seções recolhidas abaixo das questões, basta clicar nelas para expandir. Boa sorte ❤️


1. Qual o resultado?
function sayHi() {
  console.log(name);
  console.log(age);
  var name = "Lydia";
  let age = 21;
}

sayHi();
  • A: Lydia e undefined
  • B: Lydia e ReferenceError
  • C: ReferenceError e 21
  • D: undefined e ReferenceError
Resposta

Resposta: D

Dentro da função, nós primeiro declaramos a variável name usando a palavra-chave var. Isso significa que a variavel é elevada(hoisted) (O espaço na memória é separado durante a fase de criação) com o valor padrão undefined, até que chegue na linha onde definimos a variável. Ainda não definimos a variável na linha onde tentamos usar colocar no log o valor da variável name, portanto ela ainda tem o valor undefined.

Variáveis com a palavra-chave let (e const) são elevadas, mas diferente de var, não são inicializadas. Elas não estão acessíveis antes da linha em que as declaramos (ou inicializamos). Esse é um conceito chamado de "temporal dead zone". Quando tentamos acessar essas variáveis antes de serem declaradas, o JavaScript lança um ReferenceError.


2. Qual o resultado?
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1);
}
  • A: 0 1 2 e 0 1 2
  • B: 0 1 2 e 3 3 3
  • C: 3 3 3 e 0 1 2
Resposta

Resposta: C

Por causa da fila de eventos em JavaScript, a callback de setTimeout é chamada depois do laço ter sido executado. Já que a variável i no primeiro laço foi declarada usando a palavra-chave var, seu valor era global. Durante o laço, incrementamos o valor de i por 1 em cada repetição, usando o operador unário ++. Quando a callback de setTimeout foi chamada, i valia 3.

No segundo laço, a variável i foi declarada usando a palavra-chave let: Variáveis declaradas com let (e const) só são acessíveis nos escopos de seus blocos (um bloco é qualquer código entre { }). Durante cada repetição do laço, i vai ter um novo valor, e cada valor tem seu escopo dentro do laço.


3. Qual o resultado?
const shape = {
  radius: 10,
  diameter() {
    return this.radius * 2;
  },
  perimeter: () => 2 * Math.PI * this.radius
};

shape.diameter();
shape.perimeter();
  • A: 20 e 62.83185307179586
  • B: 20 e NaN
  • C: 20 e 63
  • D: NaN e 63
Resposta

Resposta: B

Perceba que o valor de diameter é uma função normal, enquanto que o valor de perimeter é uma arrow function.

Com arrow functions, a palavra-chave this faz referência ao escopo atual em que está inserida, diferente de funções normais! Isso significa que quando nós chamamos perimeter, ela não faz referência ao objeto shape, mas ao seu escopo atual (por exemplo, window).

Não há radius fora de shape, então retorna undefined.


4. Qual o resultado?
+true;
!"Lydia";
  • A: 1 and false
  • B: false and NaN
  • C: false and false
Resposta

Resposta: A

O operador unário + tenta converter um operando para um número. true é 1, e false é 0.

A string 'Lydia' tem valor truthy*. O que estamos realmente perguntando é "Esse valor truthy é falsy?". Isso retorna false.

*Nota do tradutor: truthy é um termo único ao JavaScript que denota valores que podem ser convertidos em um booleano True. Sua contraparte é falsy, que são valores que podem ser convertidos em um booleano false. Para fins de consistência, mantenho os termos originais.


5. Qual é a alternativa correta?
const bird = {
  size: "small"
};

const mouse = {
  name: "Mickey",
  small: true
};
  • A: mouse.bird.size não é válido
  • B: mouse[bird.size] não é válido
  • C: mouse[bird["size"]] não é válido
  • D: Todos são válidos
Resposta

Resposta: A

No JavaScript, todas chaves dos objetos são strings (a não ser que sejam um símbolo). Ainda que não possamos digitá-las como strings, elas são sempre convertidas para string sob o capô.

JavaScript interpreta afirmações. Quando usamos a notação de colchetes, ele vê o colchete de abertura [ e continua lendo até encontrar o colchete que o fecha ]. Só então vai avaliar e rodar as afirmações.

mouse[bird.size]: Primeiro avalia bird.size, que é "small". mouse["small"] retorna true

Por outro lado, com a notação de ponto ., isso não acontece. mouse não tem uma chave chamada bird, o que significa que mouse.bird é undefined. Então, pedimos pelo size usando a notação de ponto: mouse.bird.size. Uma vez que mouse.bird é undefined, estamos realmente pedindo undefined.size. Isso não é válido, e irá gerar um erro similar a Cannot read property "size" of undefined.


6. Qual o resultado?
let c = { greeting: "Hey!" };
let d;

d = c;
c.greeting = "Hello";
console.log(d.greeting);
  • A: Hello
  • B: Hey
  • C: undefined
  • D: ReferenceError
  • E: TypeError
Resposta

Resposta: A

Em JavaScript, todos objetos interagem por referência quando os colocamos um igual ao outro.

Primeiro, a variável c guarda o valor de um objeto. Depois, declaramos d com a mesma referencia que c tem para o objeto.

Quando você muda um objeto, você muda todos eles.


7. Qual o resultado?
let a = 3;
let b = new Number(3);
let c = 3;

console.log(a == b);
console.log(a === b);
console.log(b === c);
  • A: true false true
  • B: false false true
  • C: true false false
  • D: false true true
Resposta

Resposta: C

new Number() é uma funcção construtura padrão do JavaScript. Ainda que parece com um número, não é realmente um número: Tem um monte de funções extras e é um objeto.

Quando usamos o operador ==, só conferimos se ambas tem o mesmo valor. Ambas tem o valor de 3, então retorna true.

Contudo, quando usamos o operador ===, ambos valor e tipo tem de ser o mesmo. E não são: new Number() não é um número, é um objeto. Ambos retornam false.


8. Qual o resultado?
class Chameleon {
  static colorChange(newColor) {
    this.newColor = newColor;
    return this.newColor;
  }

  constructor({ newColor = "green" } = {}) {
    this.newColor = newColor;
  }
}

const freddie = new Chameleon({ newColor: "purple" });
freddie.colorChange("orange");
  • A: orange
  • B: purple
  • C: green
  • D: TypeError
Resposta

Resposta: D

A função colorChange é estática. Métodos estáticos são designados para viver somente nos construtores em que são criados, e filhos não herdam esses métodos. Já que freddie é filho de Chameleon, a função não é herdada, e não está disponível para freddie: Um erro TypeError é gerado.


9. Qual o resultado?
let greeting;
greetign = {}; // Erro de digitação!
console.log(greetign);
  • A: {}
  • B: ReferenceError: greetign is not defined
  • C: undefined
Resposta

Resposta: A

Cria o log do objeto, pois criamos um objeto vazio no objeto global! Quando erramos a digitação de greeting como greetign, o interpretador do JavaScript viu isso como global.greetign = {} (ou window.greetign = {} em um navegador).

Para evitar esse comportamento, podemos usar "use strict". Isso garante que você tenha declarado uma variável antes de poder inicializá-la com algum valor.


10. O que acontece quando fazemos isso?
function bark() {
  console.log("Woof!");
}

bark.animal = "dog";
  • A: Nada, isso é ok!
  • B: SyntaxError. Não se pode adicionar propriedades em uma função dessa maneira.
  • C: undefined
  • D: ReferenceError
Resposta

Resposta: A

Isso é possível em JavaScript, pois funções são objetos! (Tudo menos tipos primitivos são objetos)

Uma função é um tipo especial de objeto. O código que você escreve não é a verdadeira função. A função é um objeto com propriedades. E essa propriedade é invocável.


11. Qual o resultado?
function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const member = new Person("Lydia", "Hallie");
Person.getFullName = function() {
  return `${this.firstName} ${this.lastName}`;
};

console.log(member.getFullName());
  • A: TypeError
  • B: SyntaxError
  • C: Lydia Hallie
  • D: undefined undefined
Resposta

Resposta: A

Você não pode adicionar propriedades para um construtor igual aos objetos normais. Se você quer adicionar uma funcionalidade para todos objetos ao mesmo tempo, você deve usar o prototype.

Então nesse caso

Person.prototype.getFullName = function() {
  return `${this.firstName} ${this.lastName}`;
};

faria member.getFullName() funcionar. Por quê isso é beneficial? Digamos que tivéssemos esse método no próprio construtor. Talvez nem toda instância de Person precisasse desse método. Isso gastaria muita memória, uma vez que cada instância teria esse propriedade e teria seu espaço alocado. Ao invés disso, se adicionarmos somente ao protótipo, alocamos somente um único espaço na memória, e todas instâncias de Person ainda tem acesso ao método.


12. Qual o resultado?
function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const lydia = new Person("Lydia", "Hallie");
const sarah = Person("Sarah", "Smith");

console.log(lydia);
console.log(sarah);
  • A: Person {firstName: "Lydia", lastName: "Hallie"} e undefined
  • B: Person {firstName: "Lydia", lastName: "Hallie"} e Person {firstName: "Sarah", lastName: "Smith"}
  • C: Person {firstName: "Lydia", lastName: "Hallie"} e {}
  • D:Person {firstName: "Lydia", lastName: "Hallie"} e ReferenceError
Resposta

Resposta: A

Na sarah, não usamos a palavra-chave new. Quando usamos new, se refere ao novo objeto vazio que criamos. Contudo, se não usarmos new, nos referimos ao objeto global!

Afirmamos que this.firstName vale "Sarah" e this.lastName vale "Smith". O que realmente fizemos foi definir global.firstName = 'Sarah' e global.lastName = 'Smith'. A sarah ainda é undefined.


13. Quais são as três fases na propagação de eventos?
  • A: Target > Capturing > Bubbling
  • B: Bubbling > Target > Capturing
  • C: Target > Bubbling > Capturing
  • D: Capturing > Target > Bubbling
Resposta

Resposta: D

Durate a fase do capturing, o evento percorre os elementos pais até chegar no elemento algo. Isso alcança o elemento target, e o bubbling começa.

*Nota do tradutor: bubbling descreve uma forma específica de propagação de eventos. Em tradução livre é "borbulhar", que indica como os eventos "sobem" a cadeia onde estão aninhados, mas prefiro por manter o original, visto que é o nome dessa forma de propagação.


14. Todos objetos tem protótipos.
  • A: Verdadeiro
  • B: Falso
Resposta

Resposta: B

Todos objetos tem protótipos, exceto pelo base object. O base object tem acesso à alguns métodos e propriedades, como .toString. É o motivo de podermos usar métodos já embutidos no JavaScript! Todos métodos desse tipo já estão embutidos no protótipo. Apesar do JavaScript não encontrar algum método diretamente no seu objeto, ele percorre a cadeia de protótipos até encontrar no base, o que torna acessível para todo objeto.


15. Qual o resultado?
function sum(a, b) {
  return a + b;
}

sum(1, "2");
  • A: NaN
  • B: TypeError
  • C: "12"
  • D: 3
Resposta

Resposta: C

JavaScript é uma linguagem dinamicamente tipada: Não especificamos quais tipos nossas variáveis são. Valores pode ser automaticamente convertidos em outro tipo sem você saber, o que é chamado de coerção implicita de tipo. Coerção é converter de um tipo em outro.

Nesse exemplo, JavaScript converte o número 1 em uma string, para que a função faça sentido e retorne um valor. Durante a adição de um tipo numérico (1) e uma string ('2'), o número é tratado como uma string. Podemos concatenar strings como "Hello" + "World", então o que está acontecendo aqui é "1" + "2" que retorna "12".


16. Qual o resultado?
let number = 0;
console.log(number++);
console.log(++number);
console.log(number);
  • A: 1 1 2
  • B: 1 2 2
  • C: 0 2 2
  • D: 0 1 2
Resposta

Resposta: C

O operador unário no sufixo ++:

  1. Retorna o valor (retorna o valor 0)
  2. Incrementa o valor (numero agora é 1)

O operador unário prefixo ++:

  1. Incrementa o valor (numero agora é 2)
  2. Retorna o valor (Retorna o valor 2)

Isso retorna 0 2 2.


17. Qual o resultado?
function getPersonInfo(one, two, three) {
  console.log(one);
  console.log(two);
  console.log(three);
}

const person = "Lydia";
const age = 21;

getPersonInfo`${person} is ${age} years old`;
  • A: "Lydia" 21 ["", " is ", " years old"]
  • B: ["", " is ", " years old"] "Lydia" 21
  • C: "Lydia" ["", " is ", " years old"] 21
Resposta

Resposta: B

Se usamos template literals marcadas, ou tagged template literals, o valor do primeiro argumento é sempre um array com a string, separada pelos tagged template liberals. Os argumentos restantes recebem os valores das expressões passadas!


18. Qual o resultado?
function checkAge(data) {
  if (data === { age: 18 }) {
    console.log("You are an adult!");
  } else if (data == { age: 18 }) {
    console.log("You are still an adult.");
  } else {
    console.log(`Hmm.. You don't have an age I guess`);
  }
}

checkAge({ age: 18 });
  • A: You are an adult!
  • B: You are still an adult.
  • C: Hmm.. You don't have an age I guess
Resposta

Resposta: C

Quando testamos igualdade, primitivos são comparados por seus valores, enquanto objetos são comparados por suas referências. O JavaScript confere se os objetos tem a referência para o mesmo local na memória.

Os dois objetos que estamos comparando não são assim: O objeto que passamos como parâmetro faz referência a uma posição na memória diferente daquela que o objeto que usamos para conferir a igualdade.

É por isso que ambos { age: 18 } === { age: 18 } E { age: 18 } == { age: 18 } retornam false.


19. Qual o resultado?
function getAge(...args) {
  console.log(typeof args);
}

getAge(21);
  • A: "number"
  • B: "array"
  • C: "object"
  • D: "NaN"
Resposta

Resposta: C

O operador spread (...args.) retorna um array com os argumentos. Um array é um objeto, então typeof args retorna "object".


20. Qual o resultado?
function getAge() {
  "use strict";
  age = 21;
  console.log(age);
}

getAge();
  • A: 21
  • B: undefined
  • C: ReferenceError
  • D: TypeError
Resposta

Resposta: C

Com "use strict", você pode ter certeza que não declarou variáveis globais. Nunca declaramos a variável age, e já que usamos "use strict", ira gerar um erro de referência. Se não tivéssemos usado "use strict", teria funcionado, uma vez que a propriedade age teria sido adicionada ao objeto global.


21. Qual o valor de sum?
const sum = eval("10*10+5");
  • A: 105
  • B: "105"
  • C: TypeError
  • D: "10*10+5"
Resposta

Resposta: A

eval executa o código mesmo se passado como string. Se é uma expressão, como nesse caso, ele calcula a expressão. A expressão é 10 * 10 + 5. Isso retorna o número 105.


22. Por quanto tempo cool_secret é acessível?
sessionStorage.setItem("cool_secret", 123);
  • A: Sempre, o dado não é perdido.
  • B: Quando o usuário fechar a guia.
  • C: Quando o usuário fechar o navegador inteiro.
  • D: Quando o usuário desligar o computador.
Resposta

Resposta: B

Dados guardados em sessionStorage são removidos depois de fechar a guia.

Se usássemos localStorage, o dado seria guardado para sempre, exceto se localStorage.clear() fosse chamado.


23. Qual o resultado?
var num = 8;
var num = 10;

console.log(num);
  • A: 8
  • B: 10
  • C: SyntaxError
  • D: ReferenceError
Resposta

Resposta: B

Coma a palavra-chave var, você pode declarar várias variáveis com o mesmo nome. A variável vai guardar o último valor.

Você não pode fazer isso com let ou const uma vez que eles conferem o bloco de escopo em que estão inseridos.


24. Qual o resultado?
const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);

obj.hasOwnProperty("1");
obj.hasOwnProperty(1);
set.has("1");
set.has(1);
  • A: false true false true
  • B: false true true true
  • C: true true false true
  • D: true true true true
Resposta

Resposta: C

Todas as chaves de objetos (exceto símbolos) são strings debaixo do capô, mesmo que você não digite como uma string. É por isso que obj.hasOwnProperty('1') também retorna true.

Não funciona assim para Set. Não tem um '1' no nosso set: set.has('1') retorna false. Temos o tipo número 1, então set.has(1) retorna true.


25. Qual o resultado?
const obj = { a: "one", b: "two", a: "three" };
console.log(obj);
  • A: { a: "one", b: "two" }
  • B: { b: "two", a: "three" }
  • C: { a: "three", b: "two" }
  • D: SyntaxError
Resposta

Resposta: C

Se temos duas chaves com o mesmo nome, a última irá substituir a primeira. Ainda vai estar na primeira posição, mas com o último valor específicado.


26. O contexto global de execução do JavaScript cria duas coisas para você: O objeto global, e a palavra-chave this.
  • A: Verdadeiro
  • B: Falso
  • C: Depende
Resposta

Resposta: A

O contexto base de execução é o contexto global: É aquilo que está acessível em qualquer lugar do código.


27. Qual o resultado?
for (let i = 1; i < 5; i++) {
  if (i === 3) continue;
  console.log(i);
}
  • A: 1 2
  • B: 1 2 3
  • C: 1 2 4
  • D: 1 3 4
Resposta

Resposta: C

A palavra-chave continue pula uma iteração se a condição retorna true.


28. Qual o resultado?
String.prototype.giveLydiaPizza = () => {
  return "Just give Lydia pizza already!";
};

const name = "Lydia";

console.log(name.giveLydiaPizza())
  • A: "Just give Lydia pizza already!"
  • B: TypeError: not a function
  • C: SyntaxError
  • D: undefined
Resposta

Resposta: A

String é um construtor embutido, no qual podemos adicionar propriedades. Nesse caso adicionamos um método ao seu protótipo. Tipos primitivos string são automaticamente convertidos em um objeto string, gerado pelo construtor String. Assim, todas as strings (que são objetos string) tem acesso ao método.


29. Qual o resultado?
const a = {};
const b = { key: "b" };
const c = { key: "c" };

a[b] = 123;
a[c] = 456;

console.log(a[b]);
  • A: 123
  • B: 456
  • C: undefined
  • D: ReferenceError
Resposta

Resposta: B

Chaves de objeto são automaticamente convertidas em strings. Estamos tentando usar um objeto como chave do objeto a, com o valor de 123.

Contudo, quando transformamos um objeto em string, ele vira um "[object Object]". Então, o que estamos afirmando é a["object Object"] = 123. Após, tentamos a mesma coisa. c é outro objeto que (implicitamente) convertemos para string. Então, temos a["object Object"] = 456.

Então, fazemos o log de a[b], o que na verdade é a["object Object"]. Acabmos de definir esse valor, como 456, e é isso que ele retorna.


30. Qual o resultado?
const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"));
const baz = () => console.log("Third");

bar();
foo();
baz();
  • A: First Second Third
  • B: First Third Second
  • C: Second First Third
  • D: Second Third First
Resposta

Resposta: B

Temos a função setTimeout e a invocamos por primeiro. Ainda assim, apareceu no log por último.

Isso acontece pois nos navegadores, não temos apenas o nosso mecanismo de execução (runtime engine), temos também algo chamado WebAPI. A WebAPI nos da coisas como a setTimeout e o DOM.

Depois que a função de retorno (callback) é enviada para a WebAPI, a função setTimeout (mas não seu retorno ou callback) são enviadas para fora do stack.

Agora, foo é chamada, e "First" é adicionado ao log.

foo é evniada para fora do stack, e baz é chamada. "Third" é adicionado ao log.

A WebAPI não pode simplesmente adicionar coisas ao stack sempre que ficam prontas. Ao invés, disso, todo retorno que fica pronto é enviado para algo chamado queue.

É aqui que um laço de evento começa a ocorrer. Um laço de evento confere o stack e o queue. Se o stack está livre, pega a primeira coisa que estiver na queue e coloca no stack.

bar é chamada, "Second" é adicionado ao log, e é enviado para fora do stack.


31. qual é o event.target quando clicamos no botão?
<div onclick="console.log('first div')">
  <div onclick="console.log('second div')">
    <button onclick="console.log('button')">
      Click!
    </button>
  </div>
</div>
  • A: A div mais externa
  • B: A div mais interna
  • C: button
  • D: Um array dos elementos aninhandos.
Resposta

Resposta: C

O elemento mais interno no aninhamento que causou o evento é o alvo do evento. Você pode parar o bubbling com event.stopPropagation.


32. Quando você clica no parágrafo, O que é adicionado ao log?
<div onclick="console.log('div')">
  <p onclick="console.log('p')">
    Click here!
  </p>
</div>
  • A: p div
  • B: div p
  • C: p
  • D: div
Resposta

Resposta: A

Se clicarmos em p, veremos dois itens adicionaos ao log: p e div. Durante a propagação de eventos, existem 3 fases: capturar, adquirir o target, e o bubbling. Por padrão, manipuladores de eventos são executados junto a fase de bubbling (a não ser que você marque useCapture como true). Percorre do elemento aninhando mais interno, propagando para fora.


33. Qual o resultado?
const person = { name: "Lydia" };

function sayHi(age) {
  console.log(`${this.name} is ${age}`);
}

sayHi.call(person, 21);
sayHi.bind(person, 21);
  • A: undefined is 21 Lydia is 21
  • B: function function
  • C: Lydia is 21 Lydia is 21
  • D: Lydia is 21 function
Resposta

Resposta: D

Com ambos, podemos passar o objeto que queremos que o this faça referência. Contudo, .call é executado imediatamente!

.bind. retorna uma cópia da função, mas com seu contexto vinculado à cópia. E não é executado imediatamente.


34. Qual o resultado?
function sayHi() {
  return (() => 0)();
}

typeof sayHi();
  • A: "object"
  • B: "number"
  • C: "function"
  • D: "undefined"
Resposta

Resposta: B

A função sayHi retorna o valor retornado pela arrow function pois ela é uma IIFE (Immediately Invoked Function Expression ou Expressão de Função Invocada Imediatamente). Essa IIFE retornou 0, que é do tipo "number".

Para saber mais: Só existem 7 tipos já definidos: null, undefined, boolean, number, string, object, symbol, e bigint. "function" não é um tipo, uma vez que funções são objetos, elas são do tipo "object".


35. Qual desses tem valor falsy?
0;
new Number(0);
("");
(" ");
new Boolean(false);
undefined;
  • A: 0, '', undefined
  • B: 0, new Number(0), '', new Boolean(false), undefined
  • C: 0, '', new Boolean(false), undefined
  • D: Todos são falsy
Resposta

Resposta: A

Existem somente seis valores falsy:

  • undefined
  • null
  • NaN
  • 0
  • '' (string vazia)
  • false

Funções construtoras, como new Number e new Boolean são truthy.


36. Qual é a sáida?
console.log(typeof typeof 1);
  • A: "number"
  • B: "string"
  • C: "object"
  • D: "undefined"
Resposta

Resposta: B

typeof 1 retorna "number". typeof "number" retorna "string"


37. Qual o resultado?
const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers);
  • A: [1, 2, 3, 7 x null, 11]
  • B: [1, 2, 3, 11]
  • C: [1, 2, 3, 7 x empty, 11]
  • D: SyntaxError
Resposta

Resposta: C

Quando você define um valor para um elemento em um array que excede o tamanho do próprio array, o JavaScript cria algo chamado "empty slots" (espaços vazios). Na verdade, esses espaços vazios tem o valor de undefined, mas você verá algo como:

[1, 2, 3, 7 x empty, 11]

dependendo de onde você o executa, pois é diferente para cada navegador, node etc.


38. Qual o resultado?
(() => {
  let x, y;
  try {
    throw new Error();
  } catch (x) {
    (x = 1), (y = 2);
    console.log(x);
  }
  console.log(x);
  console.log(y);
})();
  • A: 1 undefined 2
  • B: undefined undefined undefined
  • C: 1 1 2
  • D: 1 undefined undefined
Resposta

Resposta: A

O bloco do catch recebe o argumento x. Esse não é o mesmo x da variável de quando estamos passando os argumentos. A variável x é de escopo do seu bloco.

Depois, definimos essa variável, dentro do seu bloco, para valor 1, e definimos o valor de y, que pertence a um bloco maior. Agora, nos adicionamos ao log o valor de x, que dentro desse bloco tem valor 1.

Fora do bloco do catch. x ainda é undefined, e y ainda é 2. Quando tentamos usar console.log(x) fora do bloco do catch, isso retorna undefined, e y retorna 2.


39. Tudo em JavaScript ou é um...
  • A: primitivo ou um objeto
  • B: função ou um object
  • C: Pegadinha! Somente objetos
  • D: número ou um objeto
Resposta

Resposta: A

JavaScript tem somente tipos primitivos e objetos.

Tipos primitivos são boolean, null, undefined, bigint, number, string, e symbol.

O que diferencia um primitivo de um objeto é que primitivos não possuem métodos ou propriedades. Contudo, se você está atento vai lembrar que 'foo'.toUpperCase() retorna 'FOO' e não resulta em um TypeError. Isso acontece pois quando você tenta acessar uma propriedade ou método em um primitivo como, por exemplo, uma string, JavaScript vai transformar esse primitivo em objeto usando um wrapper, nesse caso o String, e discarta o wrapper imediatamente após executar o método ou propriedade. Todos os primitivos, com exceção de null e undefined exibem esse comportamento.


40. Qual o resultado?
[[0, 1], [2, 3]].reduce(
  (acc, cur) => {
    return acc.concat(cur);
  },
  [1, 2]
);
  • A: [0, 1, 2, 3, 1, 2]
  • B: [6, 1, 2]
  • C: [1, 2, 0, 1, 2, 3]
  • D: [1, 2, 6]
Resposta

Resposta: C

[1, 2] é nosso valor inicial. É o valor que começamos, e portanto o valor do primeiro acc. Durante a primeira iteração, acc é [1,2], e cur é [0, 1]. Nós concatemos ambos, o que resulta em [1, 2, 0, 1].

Então, [1, 2, 0, 1] é acc e [2, 3] é o cur. Concatenamos novamente, e chegamos em [1, 2, 0, 1, 2, 3].


41. Qual o resultado?
!!null;
!!"";
!!1;
  • A: false true false
  • B: false false true
  • C: false true true
  • D: true true false
Resposta

Resposta: B

null é falsy. !null retorna true. !true retorna false.

"" é falsy. !"" retorna true. !true retorna false.

1 é truthy. !1 retorna false. !false retorna true.


42. O que o método setInterval retorna no navegador?
setInterval(() => console.log("Hi"), 1000);
  • A: um id único
  • B: a quantidade de millisegundos especificada
  • C: a função passada
  • D: undefined
Resposta

Resposta: A

Retorna um id único. Esse id pode ser usado para limpar o intervalo com a função clearInterval().


43. Qual é o retorno?
[..."Lydia"];
  • A: ["L", "y", "d", "i", "a"]
  • B: ["Lydia"]
  • C: [[], "Lydia"]
  • D: [["L", "y", "d", "i", "a"]]
Resposta

Resposta: A

Strings são iteráveis. O operador do spread ... mapeia todo caractére de um iterável para um elemento.


44. Qual o resultado?
function* generator(i) {
  yield i;
  yield i * 2;
}

const gen = generator(10);

console.log(gen.next().value);
console.log(gen.next().value);
  • A: [0, 10], [10, 20]
  • B: 20, 20
  • C: 10, 20
  • D: 0, 10 e 10, 20
Resposta

Resposta: C

Funções regulares não podem ser interrompidas durante execução após sua invocação. Entretanto, uma função generator pode ser interrompida, e depois continuar de onde parou. Uma função generator sempre possue a palavra chave yield, a função gera o valor específicado logo após. Note que a função generator, neste caso não retorna o valor, ele utiliza yields no valor.

Primeiro, nós inicializamos a função generator com i igual a 10. Nós chamamos a função generator utilizando o next() para próxima função. A primeira vez que executamos a função generator o i é igual a 10. que possue a palavra chave yield: que atribue o yields ao valor de i. O generator é pausado e 10 é logado.

Então, chamamos a próxima função novamente com o next(). Que continua de onde foi interrompido anteirormente, ainda com i igual a 10. Agora, ele encontra o próximo yield, e yields i * 2. i é igual a 10, que então retorna 10 * 2, que é 20. Seu resultado é 10, 20.


45. Qual o retorno?
const firstPromise = new Promise((res, rej) => {
  setTimeout(res, 500, "one");
});

const secondPromise = new Promise((res, rej) => {
  setTimeout(res, 100, "two");
});

Promise.race([firstPromise, secondPromise]).then(res => console.log(res));
  • A: "one"
  • B: "two"
  • C: "two" "one"
  • D: "one" "two"
Resposta

Resposta: B

Quando passamos múltiplas "promises" para a função Promise.race, ele resolve ou rejeita a primeira "promise". Para a função de setTimeout, nós passamos um tempo de 500ms para a primeira promise (firstPromise), e 100ms para a segunda promise (secondPromise). Isso significa que o secondPromise resolve primeiro com o valor de 'two'. res que agora possui o valor 'two', que foi logado.


46. Qual o resultado?
let person = { name: "Lydia" };
const members = [person];
person = null;

console.log(members);
  • A: null
  • B: [null]
  • C: [{}]
  • D: [{ name: "Lydia" }]
Resposta

Resposta: D

Primeiro, declaramos a variável person com o valor de um objeto que possui o propriedade name.

Então, declaramos a variável chamada members. Setamos o valor do primeiro elemento do array igual ao valor da variável person. Objetos interados por referência quando ao defini-los iguais entre si. Quando você atribui uma referência de uma variável para outra, você faz uma cópia de sua referência. (note que eles não possuem a mesma referência!)

Então, setamos a variável person igual a null.

Estamos apenas modificando o valor da variável person, e não o primeiro elemento do array, desde que o elemento tem uma diferente referência (copiada) de um objeto. O primeiro elemento de members ainda mantém sua referência com o objeto original. Quando logamos o array de members, o primeiro elemento ainda mantém o valor do objeto, que é logado.


47. Qual o resultado?
const person = {
  name: "Lydia",
  age: 21
};

for (const item in person) {
  console.log(item);
}
  • A: { name: "Lydia" }, { age: 21 }
  • B: "name", "age"
  • C: "Lydia", 21
  • D: ["name", "Lydia"], ["age", 21]
Resposta

Resposta: B

Utilizando o loop for-in, podemos interar através das chaves do objeto, neste caso o name e age. Por baixo dos panos, chaves de objetos são strings (eles não são um símbolo). Em cada loop, setamos ao valor do item igual ao da chave atual, que se intera. Primeiro, item é igual ao name, e é logado. Então, item é igual a idade age, que é logado.


48. Qual o resultado?
console.log(3 + 4 + "5");
  • A: "345"
  • B: "75"
  • C: 12
  • D: "12"
Resposta

Resposta: B

Associatividade do operador é a ordem na qual o compilador avalia as expressões, ou esquerda-para-direita ou direita-para-esquerda. Isso apenas acontece se todos os operatores possuem a mesma precedência. Apenas temos um tipo de operador: +. Para adição, a associatividade é esquerda-para-direita.

3 + 4 é avaliado primeiro. Seu resultado é o número 7.

7 + '5' resulta em "75" por causa da coerção. JavaScript converte o número 7 em string, veja a questão 15. Podemos concatenar duas strings com o operador de +. "7" + "5" resulta em "75".


49. Qual o retorno de num?
const num = parseInt("7*6", 10);
  • A: 42
  • B: "42"
  • C: 7
  • D: NaN
Resposta

Resposta: C

Apenas os primeiros números da string é retornado. Baseado no radix (o segundo parametro na ordem especifica qual o tipo de número queremos atribuir o parse: base 10, hexadecimal, octal, binary, etc.), o parseInt checa se os caracteres na string são válidos. Depois de encontrar um caracter que não é um número válido no radix, ele interrompe o parse e ignora os seguintes caracteres.

* não é um número válido. Ele apenas usa o parse no "7" em decimal 7. num possui o valor 7.


50. Qual o resultado?
[1, 2, 3].map(num => {
  if (typeof num === "number") return;
  return num * 2;
});
  • A: []
  • B: [null, null, null]
  • C: [undefined, undefined, undefined]
  • D: [ 3 x empty ]
Resposta

Resposta: C

Quando mapeamos um array (map), o valor de num é igual ao elemento que está percorrendo. Neste caso, os elementos são números, então a condição do se (if) typeof num === "number" retorna true. A função map cria um novo array e insere os valores retornados da função.

Entretanto, não se retorna o valor. Quando não se retorna um valor para a função, a função retorna undefined. Para cada elemento do array, o bloco de função é chamado, então para cada elemento é retornado undefined.


51. Qual o resultado?
function getInfo(member, year) {
  member.name = "Lydia";
  year = "1998";
}
const person = { name: "Sarah" };
const birthYear = "1997";
getInfo(person, birthYear);
console.log(person, birthYear);
  • A: { name: "Lydia" }, "1997"
  • B: { name: "Sarah" }, "1998"
  • C: { name: "Lydia" }, "1998"
  • D: { name: "Sarah" }, "1997"
Resposta

Resposta: A

Os argumentos são passados ​​por valor. Porém, se seu valor for um objeto, eles são passados ​​por referência. birthYear é passado por valor, já que é uma string, não um objeto. Quando passamos argumentos por valor, uma cópia desse valor é criada (consulte a pergunta 46).

A variável birthYear tem uma referência ao valor "1997". O argumento year também tem uma referência ao valor "1997", mas não é o mesmo valor de referência de birthYear. Quando atualizamos o valor de year, definindo year igual a "1998", estamos apenas atualizando o valor de year. birthYear ainda é igual a "1997".

O valor de person é um objeto. O argumento member possui uma referência (copiada) do mesmo objeto . Quando modificamos uma propriedade do objeto que member tem referência, o valor de person também será modificado, pois ambos tem referência ao mesmo objeto. A propriedade name de person agora é igual ao valor "Lydia".


52. Qual o resultado?
function greeting() {
  throw "Hello world!";
}
function sayHi() {
  try {
    const data = greeting();
    console.log("It worked!", data);
  } catch (e) {
    console.log("Oh no an error:", e);
  }
}
sayHi();
  • A: It worked! Hello world!
  • B: Oh no an error: undefined
  • C: SyntaxError: can only throw Error objects
  • D: Oh no an error: Hello world!
Resposta

Resposta: D

Com a declaração throw, podemos criar erros personalizados. Com esta declaração, você pode lançar exceções. Uma exceção pode ser uma string, um número, um booleano ou um objeto. Nesse caso, nossa exceção é a string 'Hello world!'.

Com a declaração catch, podemos especificar o que fazer se uma exceção for lançada no bloco try. Uma exceção foi lançada: a string 'Hello world'. e agora é igual a essa string que registramos. Isso resulta em 'Oh no an error: Hello world!'.


53. Qual o resultado?
function Car() {
  this.make = "Lamborghini";
  return { make: "Maserati" };
}
const myCar = new Car();
console.log(myCar.make);
  • A: "Lamborghini"
  • B: "Maserati"
  • C: ReferenceError
  • D: TypeError
Resposta

Resposta: B

Quando você retorna uma propriedade, o valor da propriedade é igual ao valor retornado, não ao valor definido na função do construtor. Retornamos a string "Maserati", então myCar.make é igual a "Maserati".


54. Qual o resultado?
(() => {
  let x = (y = 10);
})();
console.log(typeof x);
console.log(typeof y);
  • A: "undefined", "number"
  • B: "number", "number"
  • C: "object", "number"
  • D: "number", "undefined"
Resposta

Resposta: A

let x = y = 10; é na realidade uma abreviação de:

y = 10;
let x = y;

Quando definimos y igual a 10, adicionamos na verdade uma propriedade y ao objeto global (window no navegador, global no Node). Em um navegador, window.y agora é igual a 10.

Então, declaramos uma variável x com o valor de y, que é 10. As variáveis ​​declaradas com let tem escopo definido no bloco ou seja, são definidas apenas dentro do bloco em que são declaradas, neste caso, immediately-invoked function (IIFE). Quando usamos o operador typeof, o operando x não está definido: estamos tentando acessar x fora do bloco em que está declarado. Isso significa que x não está definido. Os valores que não foram atribuídos ou declarados a um valor são do tipo "undefined". console.log(typeof x) retorna "undefined".

No entanto, criamos uma variável global y ao definir y igual a 10. Este valor está acessível em qualquer lugar do nosso código. y é definido e mantém um valor do tipo "number". console.log(typeof y) retorna "number".


55. Qual o resultado?
class Dog {
  constructor(name) {
    this.name = name;
  }
}
Dog.prototype.bark = function() {
  console.log(`Woof I am ${this.name}`);
};
const pet = new Dog("Mara");
pet.bark();
delete Dog.prototype.bark;
pet.bark();
  • A: "Woof I am Mara", TypeError
  • B: "Woof I am Mara", "Woof I am Mara"
  • C: "Woof I am Mara", undefined
  • D: TypeError, TypeError
Resposta

Resposta: A

Podemos excluir propriedades de objetos usando delete, também no prototype. Ao excluir uma propriedade no prototype, ela não está mais disponível na cadeia de prototypes. Nesse caso, a função bark não está mais disponível no prototype depois de delete Dog.prototype.bark, mas ainda tentamos acessá-lo.

Quando tentamos invocar algo que não é uma função, um TypeError é lançado. Neste caso, TypeError: pet.bark is not a function, uma vez que pet.bark é undefined.


56. Qual o resultado?
const set = new Set([1, 1, 2, 3, 4]);
console.log(set);
  • A: [1, 1, 2, 3, 4]
  • B: [1, 2, 3, 4]
  • C: {1, 1, 2, 3, 4}
  • D: {1, 2, 3, 4}
Resposta

Resposta: D

O objeto Set é uma coleção de valores exclusivos : um valor pode ocorrer apenas uma vez.

Passamos o iterável [1, 1, 2, 3, 4] com um valor 1 duplicado. Como não podemos ter dois dos mesmos valores em um conjunto, um deles é removido. Isso resulta em {1, 2, 3, 4}.


57. Qual o resultado?
// counter.js
let counter = 10;
export default counter;
// index.js
import myCounter from "./counter";
myCounter += 1;
console.log(myCounter);
  • A: 10
  • B: 11
  • C: Error
  • D: NaN
Resposta

Resposta: C

Um módulo importado é somente leitura: você não pode modificar o módulo importado. Somente o módulo que os exporta pode alterar seu valor.

Quando tentamos aumentar o valor de myCounter, recebemos um erro: myCounter é somente leitura e não pode ser modificado.


58. Qual o resultado?
const name = "Lydia";
age = 21;
console.log(delete name);
console.log(delete age);
  • A: false, true
  • B: "Lydia", 21
  • C: true, true
  • D: undefined, undefined
Resposta

Resposta: A

O operador delete retorna um valor booleano: true em uma exclusão bem-sucedida, caso contrário, ele retorna false. No entanto, variáveis declaradas com var, const ou let não podem ser excluídas usando o operador delete.

A variável name foi declarada com const, portanto sua exclusão não é bem-sucedida: false é retornado. Quando definimos age igual a 21, na verdade adicionamos uma propriedade chamada age para o objeto global. Dessa forma, você pode excluir propriedades dos objetos, portanto delete age returns true.


59. Qual o resultado?
const numbers = [1, 2, 3, 4, 5];
const [y] = numbers;
console.log(y);
  • A: [[1, 2, 3, 4, 5]]
  • B: [1, 2, 3, 4, 5]
  • C: 1
  • D: [1]
Resposta

Resposta: C

Podemos descompactar valores de matrizes ou propriedades de objetos através da desestruturação. Por exemplo:

[a, b] = [1, 2];

O valor de a agora é 1 e o valor de b agora é 2. O que realmente fizemos na pergunta é:

[y] = [1, 2, 3, 4, 5];

Isso significa que o valor de y é igual ao primeiro valor no array, que é o número 1. Quando registramos no console y, 1 é retornado.


60. Qual o resultado?
const user = { name: "Lydia", age: 21 };
const admin = { admin: true, ...user };
console.log(admin);
  • A: { admin: true, user: { name: "Lydia", age: 21 } }
  • B: { admin: true, name: "Lydia", age: 21 }
  • C: { admin: true, user: ["Lydia", 21] }
  • D: { admin: true }
Resposta

Resposta: B

É possível combinar objetos usando o operador o spread operator .... Ele permite criar cópias dos pares de um objeto e adicioná-las a outro objeto. Nesse caso, criamos cópias do objeto user e as adicionamos ao objeto admin. O objeto admin agora contém os pares de chave/valor copiados, o que resulta em { admin: true, name: "Lydia", age: 21 }.


61. Qual é saída?
const person = { name: "Lydia" };

Object.defineProperty(person, "age", { value: 21 });

console.log(person);
console.log(Object.keys(person));
  • A: { name: "Lydia", age: 21 }, ["name", "age"]
  • B: { name: "Lydia", age: 21 }, ["name"]
  • C: { name: "Lydia"}, ["name", "age"]
  • D: { name: "Lydia"}, ["age"]
Resposta

Resposta: B

Com o método defineProperty, podemos adicionar novas propriedades a um objeto ou modificar propriedades já existentes. Quando adicionamos uma propriedade a um objeto usando o método defineProperty, ela é, por padrão, não enumerável. O métodoObject.keys retorna todos os nomes de uma propriedade enumerável de um objeto. Nesse caso, apenas "name".

Propriedades adicionadas usando o método defineProperty são imutáveis por padrão. Você pode sobrepor esse comportamento usando as propriedade writable, configurable e enumerable. Assim, o método defineProperty dá a você muito mais controle sobre as propriedades que você está adicionando a um objeto.


62. Qual o resultado?
const settings = {
  username: "lydiahallie",
  level: 19,
  health: 90
};

const data = JSON.stringify(settings, ["level", "health"]);
console.log(data);
  • A: "{"level":19, "health":90}"
  • B: "{"username": "lydiahallie"}"
  • C: "["level", "health"]"
  • D: "{"username": "lydiahallie", "level":19, "health":90}"
Resposta

Resposta: A

O segundo argumento de JSON.stringify é o substituo. O substituto pode ser uma função ou um array, e deixa você controlar o que deve ser "stringfied", isto é, ser usado pelo método JSON.stringfy.

Se o substituto (replacer) for um array, apenas os nomes de propriedades incluídos no array serão adicionados à string JSON. Nesse caso, apenas as propriedades com os nomes "level" ed "health" são incluída, "username" é excluída. data agora é igual a "{"level":19, "health":90}".

Se o substituto (replacer) for uma função, essa função é chamada em c ada propriedade no objeto que está sendo "Stringfied". O valor retornado dessa função será o valor da propriedade quanto adicionado à string JSON. Se o valor for undefined, essa propriedade é excluída da string JSON.


63. Qual o resultado?
let num = 10;

const increaseNumber = () => num++;
const increasePassedNumber = number => number++;

const num1 = increaseNumber();
const num2 = increasePassedNumber(num1);

console.log(num1);
console.log(num2);
  • A: 10, 10
  • B: 10, 11
  • C: 11, 11
  • D: 11, 12
Resposta

Resposta: A

O operador unário ++ primeiro retorna o valor do operando, depois incrementa esse valor. O valor de num1 é 10, pois a função increaseNumber retorna primeiro o valor de num, que é 10, e apenas incrementa o valor de num posteriormente.

num2 é 10, já que passamos num1 para o increasePassedNumber. number é igual a 10 (o valor de num1. Novamente, o operador unário ++ primeiro retorna o valor do operando, depois aumenta esse valor. O valor de number é 10, então num2 é igual a 10.


64. Qual o resultado?
const value = { number: 10 };

const multiply = (x = { ...value }) => {
  console.log((x.number *= 2));
};

multiply();
multiply();
multiply(value);
multiply(value);
  • A: 20, 40, 80, 160
  • B: 20, 40, 20, 40
  • C: 20, 20, 20, 40
  • D: NaN, NaN, 20, 40
Resposta

Resposta: C

No ES6, podemos inicializar parâmetros com um valor padrão. O valor do parâmetro será o valor padrão, se nenhum outro valor tiver sido passado para a função ou se o valor do parâmetro for "undefined". Nesse caso, espalhamos (spread) as propriedades do objeto value para um novo objeto, para que x tenha o valor padrão de {number: 10}.

O argumento padrão é executado a cada chamada! Toda vez que chamamos a função, um novo objeto é criado. Invocamos a função multiply as duas primeiras vezes sem passar um valor: x tem o valor padrão de {number: 10}. Em seguida, registramos (log) o valor multiplicado desse número, que é 20.

Na terceira vez que invocamos multiply, passamos um argumento: o objeto chamado value. O operador *= é na verdade uma abreviação de x.number = x.number * 2: modificamos o valor de x.number e registramos (log) o valor multiplicado 20.

Na quarta vez, passamos o objeto value novamente. x.number foi modificado anteriormente para 20, então x.number *= 2 registra 40.


65. Qual o resultado?
[1, 2, 3, 4].reduce((x, y) => console.log(x, y));
  • A: 1 2 and 3 3 and 6 4
  • B: 1 2 and 2 3 and 3 4
  • C: 1 undefined and 2 undefined and 3 undefined and 4 undefined
  • D: 1 2 and undefined 3 and undefined 4
Resposta

Resposta: D

O primeiro argumento que o método reduce recebe é o acumulador, x neste caso. O segundo argumento é o valor atual, y. Com o método reduce, executamos uma função de retorno de chamada (callback function) em todos os elementos da matriz, o que pode resultar em um único valor.

Neste exemplo, não estamos retornando nenhum valor, estamos simplesmente registrando os valores do acumulador e o valor atual.

O valor do acumulador é igual ao valor retornado anteriormente da função de retorno de chamada (callback function). Se você não passar o argumento opcional initialValue para o método reduce, o acumulador será igual ao primeiro elemento na primeira chamada.

Na primeira chamada, o acumulador (x) é 1 e o valor atual (y) é 2. Não retornamos da função de retorno de chamada, registramos o acumulador e o valor atual: 1 e 2 são registrados.

Se você não retornar um valor de uma função, ele retornará undefined. Na próxima chamada, o acumulador é "undefined" e o valor atual é "3". undefined e 3 são registrados.

Na quarta chamada, novamente não retornamos nada da função de retorno de chamada. O acumulador é novamente undefined e o valor atual é 4. undefined e 4 são registrados.


66. Com qual construtor podemos estender com sucesso a classe Dog?
class Dog {
  constructor(name) {
    this.name = name;
  }
};

class Labrador extends Dog {
  // 1
  constructor(name, size) {
    this.size = size;
  }
  // 2
  constructor(name, size) {
    super(name);
    this.size = size;
  }
  // 3
  constructor(size) {
    super(name);
    this.size = size;
  }
  // 4
  constructor(name, size) {
    this.name = name;
    this.size = size;
  }

};
  • A: 1
  • B: 2
  • C: 3
  • D: 4
Resposta

Resposta: B

Em uma classe derivada, você não pode acessar a palavra-chave this antes de chamar super. Se você tentar fazer isso, ele lançará um erro de referência (ReferenceError): 1 e 4 lançará um erro de referência.

Com a palavra-chave super, chamamos o construtor dessa classe pai com os argumentos fornecidos. O construtor do pai recebe o argumento name, portanto, precisamos passar name para super.

A classe Labrador recebe dois argumentos, name, pois estende Dog, e size como uma propriedade extra na classe Labrador. Ambos precisam ser passados para a função construtora no Labrador, que é feita corretamente usando o construtor 2.


67. Qual o resultado?
// index.js
console.log('running index.js');
import { sum } from './sum.js';
console.log(sum(1, 2));

// sum.js
console.log('running sum.js');
export const sum = (a, b) => a + b;
  • A: running index.js, running sum.js, 3
  • B: running sum.js, running index.js, 3
  • C: running sum.js, 3, running index.js
  • D: running index.js, undefined, running sum.js
Resposta

Resposta: B

Com a palavra-chave import, todos os módulos importados são pre-parsed. Isso significa que os módulos importados são executados primeiro, o código no arquivo que importa o módulo é executado depois.

Esta é uma diferença entre require() no CommonJS e import! Com require(), você pode carregar dependências sob demanda enquanto o código está sendo executado. Se tivéssemos usado require em vez de import, running index.js, running sum.js, 3 teriam sido registrados no console.


68. Qual o resultado?
console.log(Number(2) === Number(2));
console.log(Boolean(false) === Boolean(false));
console.log(Symbol('foo') === Symbol('foo'));
  • A: true, true, false
  • B: false, true, false
  • C: true, false, true
  • D: true, true, true
Resposta

Resposta: A

Todo símbolo (Symbol) é totalmente único. O objetivo do argumento passado ao símbolo é fornecer uma descrição ao símbolo. O valor do símbolo não depende do argumento passado. Ao testarmos a igualdade, estamos criando dois símbolos totalmente novos: o primeiro Symbol('foo') e o segundo Symbol('foo'). Esses dois valores são únicos e não são iguais entre si, Symbol('foo') === Symbol('foo') retorna false.


69. Qual o resultado?
const name = 'Lydia Hallie';
console.log(name.padStart(13));
console.log(name.padStart(2));
  • A: "Lydia Hallie", "Lydia Hallie"
  • B: " Lydia Hallie", " Lydia Hallie" ("[13x whitespace]Lydia Hallie", "[2x whitespace]Lydia Hallie")
  • C: " Lydia Hallie", "Lydia Hallie" ("[1x whitespace]Lydia Hallie", "Lydia Hallie")
  • D: "Lydia Hallie", "Lyd",
Resposta

Resposta: C

Com o método padStart, podemos adicionar preenchimento (padding) ao início de uma string. O valor passado para esse método é o comprimento total da string junto com o preenchimento. A string "Lydia Hallie" tem um comprimento de 12. name.padStart(13) insere 1 espaço no início da string, porque 12 + 1 é 13.

Se o argumento passado para o método padStart for menor que o comprimento da matriz, nenhum preenchimento será adicionado.


70. Qual o resultado?
console.log('🥑' + '💻');
  • A: "🥑💻"
  • B: 257548
  • C: A string containing their code points
  • D: Error
Resposta

Resposta: A

Com o operador +, você pode concatenar seqüências de caracteres (strings). Neste caso, estamos concatenando a string "🥑" com a string "💻", resultando em "🥑💻".


71. Como podemos registrar os valores comentados após a instrução console.log?
function* iniciarJogo() {
  const resposta = yield 'Você ama JavaScript?';
  if (resposta !== 'Sim') {
    return "Uau... Acho que entramos aqui";
  }
  return 'O JavaScript também ama você ❤️';
}

const jogo = iniciarJogo();
console.log(/* 1 */); // Você ama JavaScript?
console.log(/* 2 */); // O JavaScript também ama você ❤️
  • A: jogo.next("Sim").value and jogo.next().value
  • B: jogo.next.value("Sim") and jogo.next.value()
  • C: jogo.next().value and jogo.next("Sim").value
  • D: jogo.next.value() and jogo.next.value("Sim")
Resposta

Resposta: C

Uma função geradora "pausa" a sua execução quando encontra a palavra-chave yield. Primeiro, temos que deixar a função produzir a string "Você ama JavaScript?", o que pode ser feito chamando game.next().value.

Cada linha é executada, até encontrar a primeira palavra-chave yield. Há uma palavra-chave yield na primeira linha da função: a execução para com o primeiro retorno! Isso significa que a variável resposta ainda não foi definida!

Quando chamamos game.next("Sim").value, o yield anterior é substituído pelo valor dos parâmetros passados para a função next(), "Sim" neste caso. O valor da variável "resposta" agora é igual a "Sim". A condição da instrução if retorna false e JavaScript também ama você ❤️ é registrada.


72. Qual é o resultado?
console.log(String.raw`Hello\nworld`);
  • A: Hello world!
  • B: Hello
         world
  • C: Hello\nworld
  • D: Hello\n
         world
Answer

Answer: C

String.raw retorna um texto onde os escape (\n, \v, \t etc.) são ignorados! As barras invertidas podem ser um problema, pois você pode acabar com algo como:

caminho const = `C:\Documents\Projects\table.html`

O que resultaria em:

"C:DocumentsProjectstable.html"

Com String.raw, ele simplesmente ignoraria o escape e imprimiria:

C:\Documents\Projects\table.html

Neste caso, a string é Hello\nworld, que é registrada.


73. Qual o resultado?
async function getData() {
  return await Promise.resolve('I made it!');
}

const data = getData();
console.log(data);
  • A: "I made it!"
  • B: Promise {<resolved>: "I made it!"}
  • C: Promise {<pending>}
  • D: undefined
Answer

Resposta: C

Uma função assíncrona sempre retorna uma promise. O await ainda tem que esperar que a promise seja resolvida: uma promise pendente é retornada quando chamamos getData() para definir data igual a ela.

Se quiséssemos ter acesso ao valor resolvido "I made it", poderíamos ter usado o método .then() em data:

data.then(res => console.log(res))

Isso teria registrado "Consegui!"


74. Qual o resultado?
function addToList(item, list) {
  return list.push(item);
}

const result = addToList('apple', ['banana']);
console.log(result);
  • A: ['apple', 'banana']
  • B: 2
  • C: true
  • D: undefined
Answer

Answer: B

O método .push() retorna o length do novo array! Anteriormente, a matriz continha um elemento (a string "banana") e tinha um comprimento de 1. Depois de adicionar a string "apple" ao array, o array contém dois elementos e tem um comprimento de 2. Isso é retornado da função addToList.

O método push modifica o array original. Se você quisesse retornar o array da função ao invés do tamanho do array, você deveria ter retornado list depois de enviar item para ele.


75. Qual o resultado?
const box = { x: 10, y: 20 };

Object.freeze(box);

const shape = box;
shape.x = 100;

console.log(shape);
  • A: { x: 100, y: 20 }
  • B: { x: 10, y: 20 }
  • C: { x: 100 }
  • D: ReferenceError
Answer

Answer: B

Object.freeze torna impossível adicionar, remover ou modificar propriedades de um objeto (a menos que o valor da propriedade seja outro objeto).

Quando criamos a variável shape e a definimos igual ao objeto congelado box, shape também se refere a um objeto congelado. Você pode verificar se um objeto está congelado usando Object.isFrozen. Neste caso, Object.isFrozen(shape) retorna true, pois a variável shape tem uma referência a um objeto congelado.

Como shape está congelado, e como o valor de x não é um objeto, não podemos modificar a propriedade x. x ainda é igual a 10, e { x: 10, y: 20 } é registrado.


76.Qual o resultado?
const { name: myName } = { name: 'Lydia' };

console.log(name);
  • A: "Lydia"
  • B: "myName"
  • C: undefined
  • D: ReferenceError
Answer

Answer: C

Quando descompactamos a propriedade name do objeto do lado direito, atribuímos seu valor "Lydia" a uma variável com o nome myName.

Com { name: myName }, informamos ao JavaScript que queremos criar uma nova variável chamada myName com o valor da propriedade name no lado direito.

Como tentamos registrar name, uma variável que não está definida, undefined é retornado na atribuição do lado esquerdo. Mais tarde, o valor de Lydia é armazenado através da atribuição de desestruturação.


77. É uma função pura?
function sum(a, b) {
  return a + b;
}
  • A: Yes
  • B: No
Answer

Answer: A

Uma função pura é uma função que sempre retorna o mesmo resultado, se os mesmos argumentos forem passados.

A função sum sempre retorna o mesmo resultado. Se passarmos 1 e 2, ele sempre retornará 3 sem efeitos colaterais. Se passarmos 5 e 10, ele sempre retornará 15, e assim por diante. Esta é a definição de uma função pura.


78. Qual o resultado?
const add = () => {
  const cache = {};
  return num => {
    if (num in cache) {
      return `From cache! ${cache[num]}`;
    } else {
      const result = num + 10;
      cache[num] = result;
      return `Calculated! ${result}`;
    }
  };
};

const addFunction = add();
console.log(addFunction(10));
console.log(addFunction(10));
console.log(addFunction(5 * 2));
  • A: Calculated! 20 Calculated! 20 Calculated! 20
  • B: Calculated! 20 From cache! 20 Calculated! 20
  • C: Calculated! 20 From cache! 20 From cache! 20
  • D: Calculated! 20 From cache! 20 Error
Answer

Answer: C

A função add é uma função memoized. Com a memorização, podemos armazenar em cache os resultados de uma função para acelerar sua execução. Nesse caso, criamos um objeto cache que armazena os valores retornados anteriormente.

Se chamarmos a função addFunction novamente com o mesmo argumento, ela primeiro verifica se já obteve esse valor em seu cache. Se for o caso, o valor dos caches será retornado, o que economiza tempo de execução. Caso contrário, se não estiver armazenado em cache, ele calculará o valor e o armazenará posteriormente.

Chamamos a função addFunction três vezes com o mesmo valor: na primeira chamada, o valor da função quando num é igual a 10 ainda não é armazenado em cache. A condição da instrução if num in cache retorna false, e o bloco else é executado: Calculated! 20 é registrado e o valor do resultado é adicionado ao objeto de cache. cache agora se parece com{10:20}.

Na segunda vez, o objeto cache contém o valor que é retornado para 10. A condição da instrução if num in cache retorna true, e 'From cache! 20' é registrado.

Na terceira vez, passamos 5 * 2 para a função que é avaliada como 10. O objeto cache contém o valor que é retornado para 10. A condição da instrução if num in cache retorna true, e 'From cache! 20' é registrado.


79. Qual o resultado?
const myLifeSummedUp = ['☕', '💻', '🍷', '🍫'];

for (let item in myLifeSummedUp) {
  console.log(item);
}

for (let item of myLifeSummedUp) {
  console.log(item);
}
  • A: 0 1 2 3 and "☕" "💻" "🍷" "🍫"
  • B: "☕" "💻" "🍷" "🍫" and "☕" "💻" "🍷" "🍫"
  • C: "☕" "💻" "🍷" "🍫" and 0 1 2 3
  • D: 0 1 2 3 and {0: "☕", 1: "💻", 2: "🍷", 3: "🍫"}
Answer

Answer: A

Com um loop for-in, podemos iterar sobre propriedades enumeráveis​​. Em um array, as propriedades enumeráveis ​​são as "chaves" dos elementos do array, que na verdade são seus índices. Você pode ver uma matriz como:

{0:" ☕ ", 1:" 💻 ", 2:" 🍷 ", 3:" 🍫 "}

Onde as chaves são as propriedades enumeráveis. 0`` 1 2`` 3 são registrados.

Com um loop for-of, podemos iterar sobre iteráveis. Um array é um iterável. Quando iteramos sobre o array, a variável "item" é igual ao elemento sobre o qual está iterando no momento, " ☕ " " 💻 " " 🍷 " " 🍫 " são registrados.


80. Qual o resultado?
const list = [1 + 2, 1 * 2, 1 / 2];
console.log(list);
  • A: ["1 + 2", "1 * 2", "1 / 2"]
  • B: ["12", 2, 0.5]
  • C: [3, 2, 0.5]
  • D: [1, 1, 1]
Answer

Answer: C

Os elementos da matriz podem conter qualquer valor. Números, strings, objetos, outras matrizes, valores nulos, booleanos, indefinidos e outras expressões, como datas, funções e cálculos.

O elemento será igual ao valor retornado. 1 + 2 retorna 3, 1 * 2 retorna 2 e 1 / 2 retorna 0,5.