¡Te damos la bienvenida a este reto!

1

¡Bienvenido al mundo de JavaScript!

Día 1

2

Variables, funciones y sintaxis básica

3

Tipos de datos

4

Playground - Retorna el tipo

5

Tipos de datos - pt 2

Día 2

6

Operadores

7

Hoisting y coerción

8

Playground - Calcula la propina

9

Alcance de las variables

Día 3

10

Condicionales

11

Playground - Calcula años bisiestos

12

Switch

13

Playground - Obten información de mascotas según su tipo

14

Ciclos

15

Playground - Dibuja un triangulo

Día 4

16

Arrays

17

Playground - Encuentra al michi mas famoso

18

Objetos

19

Playground - Obten el promedio de los estudiantes

Día 5 - Checkpoint

20

Playground - encuentra el palindromo más grande

Día 6

21

Reasignación y redeclaración

22

Modo estricto

Día 7

23

Debugging y manejo de errores

24

Programación funcional

Quiz: Día 7

Día 8

25

Closures

26

Playground - Crea una calculadora con closures

27

Higher order functions

28

Playground - Crea tu propio método map

Día 9

29

ECMAScript

30

TC39

Quiz: Día 9

Día 10 - Checkpoint

31

ES6

32

ES7

33

Playground - Task planner

Día 11

34

Asincronismo

35

Playground - Promesas

36

Manejando el asincronismo

37

Playground - Resuelve el callback hell usando promesas

38

Playground - Resuelve el callback hell usando async/await

Día 12

39

Arrays a profundidad

40

Métodos de arrays: Every, Find y findIndex

41

Playground - Válida el formulario

Día 13

42

Métodos de arrays: Includes, Join y concat

43

Playground - agrupa los productos

44

Métodos de arrays: Flat y FlatMap

45

Playground - Encuentra la ubicación del valor buscado

Día 14

46

Mutable functions

47

Playground - Modifica una lista de compras

48

Métodos de arrays: sort

49

Playground - Ordena los productos

Día 15 - Checkpoint

50

Playground - Sistema de reservaciones de un hotel

Día 16

51

Programación orientada a objetos en JavaScript

52

Objetos literales

53

Playground - Congela el objeto recursivamente

Día 17

54

Prototipos en JavaScript

55

Playground - Modifica el prototype de los arrays

56

Playground - Crea un auto usando clases

Día 18

57

Abstracción en JavaScript

58

Playground - Sistema de carrito de compras

59

Encapsulamiento en JavaScript

60

Playground - Encapsula datos de los usuarios

Día 19

61

Herencia en JavaScript

62

Playground - Jerarquía de animales

63

Polimorfismo en JavaScript

64

Playground - Sistema de pagos

Día 20 - Checkpoint

65

Playground - Agenda de vuelos

Día 21

66

Patrones de diseño

67

Sinlgeton y Factory pattern en JavaScript

68

Playground - Implementa singleton en un chat

Día 22

69

Adapter y Decorator pattern en JavaScript

70

Playground - Personaliza productos de una tienda

71

Builder y Protype pattern en JavaScript

72

Playground - Mejora el código usando builder pattern

Día 23

73

Facade y proxy pattern en JavaScript

74

Playground - Proxy en servicio de mensajería

75

Chain of responsability y Observer pattern en JavaScript

76

Playground - Implementación de Observador en Newsletter

Día 24 - Checkpoint

77

Playground - Crea un task manager con patrones de diseño

Día 25

78

Estructuras de datos en JavaScript

79

Playground - Crea tu propia implementación de un array

80

Hash tables en JavaScript

81

Playground - Implementación de una HashTable para Contactos

Día 26

82

Set en JavaScript

83

Playground - Remueve duplicados de una lista

84

Maps en JavaScript

85

Playground - Crea un organizador de tareas

Día 27

86

Singly Linked List en JavaScript

87

Playground - Agrega métodos a la singly linked list

88

Playground - Implementación de una singly linked list

Día 28

89

Stacks en JavaScript

90

Playground - Crea un stack para una playlist

Día 29

91

Queues en JavaScript

92

Playground - Crea una cola de emails

Día 30

93

¡Lo lograste!

Live Class

94

30 días de JS con Juan DC

95

30 días de JS con Nicobytes

96

30 días de JS con GNDX

97

30 días de JS con LeoCode

98

30 días de JS con Teffcode

99

Sesión: Cierre de los 30 días de JavaScript

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Playground - Agrega métodos a la singly linked list

87/99

Aportes 22

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Mi solución:
.
.
.
.
.
.
.
.
.
.
.

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index){
    if (index < 0 || index >= this.length) {  // index fuera de rango
      return null;
    }
    let nodeCurrent = this.head;
    let i = 0;
    while (i!=index) {
      nodeCurrent = nodeCurrent.next;
      i++;
    }
    return nodeCurrent.value;
  }

  insertAt(index, value){
    if (index < 0 || index > this.length-1) {
      return null;
    }
    if (index == 0) {  //si el indice es 0 se inserta al principio
      this.prepend(value);
      return this;
    }
    if (index == this.length) {  //si el indice es igual a length, se inserta al final
      this.append(value);
      return this;
    }
    if (index > 0 && index < this.length - 1) {  //si el indice está en el medio
      const newNode = new Node(value);
      const nodoPrev = this.nodeSearch(index - 1) //buscamos al nodo previo

      newNode.next = nodoPrev.next //newNodo apunta al Nodo Posterior
      nodoPrev.next = newNode;     //nodo previo apunta al nuevo nodo
      this.length++;
      return this;
    }
  }

  toArray(){
    let values = [];
    let pointer = this.head;
    for (let i = 0; i < this.length; i++) {
      values.push(pointer.value);
      pointer = pointer.next;
    }
    return values;
  }

  removeAt(index){
    if (index < 0 || index > this.length-1) {
      return null;
    }
    if (index == 0) {  //se elimina el primer nodo
      this.head = this.head.next;
      this.length--;
      return this;
    }
    if (index == this.length - 1) {  //se elimina el último nodo
      const nodoPrev = this.nodeSearch(index - 1);
      this.tail = nodoPrev;
      nodoPrev.next = null;
      this.length--;
      return this;
    }
    if (index > 0 && index < this.length - 1) {  //si el indice está al medio
      const nodoPrev = this.nodeSearch(index - 1) //buscamos al nodo previo
      const nodoPost = this.nodeSearch(index + 1) //buscamos al nodo posterior
      nodoPrev.next = nodoPost; //el nodo previo ahora apunta al nodo posterior
      this.length--;
      return this;
    }
  }

  nodeSearch(index) {
    let pointerSearch = this.head;
    let i = 0;
    if (index < 0 || index >= this.length) {
      throw new Error("El índice esta fuera de rango");
    }
    while (i != index && pointerSearch.next != null) {
      pointerSearch = pointerSearch.next;
      i++;
    }
    return pointerSearch;
  }
}


.
.
.
.
.
.

class LinkedListRecharged extends LinkedList {
    get(index){
        if (!this.head) {
            return null;
        }
        let counter = 0;
        let currentNode = this.head;
        while (counter != index) {
            if (currentNode.next === null) {
            return null;
            }
            currentNode = currentNode.next;
            counter++;
        }
        return currentNode.value;
    }

    insertAt(index, value) {
        if (index < 0 || index > this.length) return null;
        const newNode = new Node(value);
        let currentNode = this.head;
        let previousNode = null;
        for (let i = 0; i < index; i++) {
            previousNode = currentNode;
            currentNode = currentNode.next;
        }
        if (!previousNode) {
            this.prepend(value);
        } else if (!currentNode) {
            this.append(value);
        } else {
            newNode.next = currentNode;
            previousNode.next = newNode;
            this.length++;
        }
        return null;
    }
  
    toArray() {
        let values = [];
        let currentNode = this.head;
        while (currentNode) {
            values.push(currentNode.value);
            currentNode = currentNode.next;
        }
        return values;
    }
  
    removeAt(index) {
        const value = this.get(index);
        index < 0 || index >= this.length ? null : this.delete(value);
        return value;
    }
} 

Bien, podría ser mejor, aun soy noob.

Exercise.js

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index) {
    if (!this.head) {
      return null;
    }
    let counter = 0;
    let currentNode = this.head;
    while (counter != index) {
      if (currentNode.next === null) {
        return null;
      }
      currentNode = currentNode.next;
      counter++;
    }
    return currentNode.value;
  }

  insertAt(index, value) {
    let newNode = new Node(value), counter = 0;
    let currentNode = this.head;
    if (index >= this.length || index < 0) {
      return null;
    }
    if (index === 0) {
      newNode.next = this.head;
      this.head = newNode
      this.length++;
      return;
    } else {
      while (counter != (index - 1)) {
        if (currentNode.next === null) {
          this.tail.next = newNode;
          this.tail = newNode;
          this.length++;
          return;
        }
        currentNode = currentNode.next;
        counter++;
      }
        newNode.next = currentNode.next;
        currentNode.next = newNode;
        this.length++;
        return;
    }
  }

  toArray() {
    let currentNode = this.head;
    let values = [];
    while (currentNode) {
      values.push(currentNode.value);
      currentNode = currentNode.next;
    }
    return values;
  }

  removeAt(index) {
    if (!this.head) {
      return null;
    }
    let counter = 0;
    let currentNode = this.head;
    while (counter != index - 1) {
      currentNode = currentNode.next;
      if (currentNode.next === null) {
        return null;
      }
      counter++;
    }
    let deleted = currentNode.value;
    currentNode.next = currentNode.next.next;
    this.length--;
    return deleted;
  }
}

![](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExNWEzbWR1NmlsMW5vN3NkaTlleGtjbm9icmFzMTdmdHpkY3podTEzayZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/LTYT5GTIiAMBa/giphy.gif)![]() ![](https://static.platzi.com/media/user_upload/code-6ac73ebc-419e-4b47-aef5-092471a9529a.jpg)

Al parecer tengo un error en el método insertAt() pero cuando corro mi código en un editor funciona correctamente.
.
.
.
.
.
.
.
.
.
.
.
.
.

.

  get(index){
        if(index > this.length - 1 ){
            return null
        }
    let currentNode = this.head
    for(let i = 0; i !== index; i++){
        currentNode = currentNode.next //Lo que hay que tener en cuenta 
    }
    return currentNode.value
}
       insertAt(index, value){
        let currentNode = this.head
        if(index >= this.length || index < 0) {
            return null
        }
        else if(index === 0){
            this.prepend(value)
        }
        else if(index === this.length - 1){
            this.append(value)
        }
        else {
            let i = 0
            while(i < index){
            currentNode = currentNode.next
            i++
        }
        currentNode.value = value// Remplazo
        this.length++
    } 
       }
     
       toArray(){
        let currentNode = this.head
        let valoresEstructuraLineal = []
        for(let i = 0; i !== this.length; i++){
            valoresEstructuraLineal.push(currentNode.value)
            currentNode = currentNode.next
        }
    return valoresEstructuraLineal
       }
       removeAt(index){
        let nodeDelete = this.head
        for(let i = 0; i !== index; i++){
        nodeDelete = nodeDelete.next //Lo que hay que tener en cuenta 
        }
        return this.delete(nodeDelete.value)
    }
}

Hola la solución, con ayuda de los comnentarios.
















import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index) {
    if (index < 0 || index >= this.length) {
      return null;
    }

    let currentNode = this.head;
    for (let i = 0; i < index; i++) {
      currentNode = currentNode.next;
    }

    return currentNode.value;
  }

  insertAt(index, value) {
    if (index < 0 || index >= this.length) {
      return null;
    }

    const newNode = new Node(value);

    if (index === 0) {
      newNode.next = this.head;
      this.head = newNode;

      if (!this.tail) {
        this.tail = newNode;
      }

      this.length++;

      return newNode;
    }

    let currentNode = this.head;
    for (let i = 0; i < index - 1; i++) {
      currentNode = currentNode.next;
    }

    newNode.next = currentNode.next;
    currentNode.next = newNode;

    if (!newNode.next) {
      this.tail = newNode;
    }

    this.length++;
    return newNode;
  }

  toArray() {
    const result = [];
    let currentNode = this.head;
    while (currentNode) {
      result.push(currentNode.value);
      currentNode = currentNode.next;
    }

    return result;
  }

  removeAt(index) {
    if (index < 0 || index >= this.length) {
      return null;
    }

    let deletedNode = null;

    if (index === 0) {
      deletedNode = this.head;
      this.head = this.head.next;
      if (this.length === 1) {
        this.tail = null;
      }
      this.length--;
      return deletedNode.value;
    }

    let currentNode = this.head;

    for (let i = 0; i < index - 1; i++) {
      currentNode = currentNode.next;
    }

    deletedNode = currentNode.next;
    currentNode.next = currentNode.next.next;

    if (!currentNode.next) {
      this.tail = currentNode;
    }

    this.length--;
    return deletedNode.value;
  }
}

Mi solucion:
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index){
    // Tu código aquí 👈
    if (index < 0 || index >= this.length)
      return null;
    let currentNode = this.head;
    for (let i = 0; i <= this.length - 1; i++) {
      if (index === i)
        return currentNode.value;
      currentNode = currentNode.next;
    }
  }

  insertAt(index, value){
    // Tu código aquí 👈
    const newNode = new Node(value);
    if (index < 0 || index >= this.length)
      return null;
    if (index === 0) {
      this.prepend(value);
      return;
    }
    if (index === this.length) {
      this.append(value);
      return;
    }
    let currentNode = this.head;
    let prevNode;
    for (let i = 0; i <= this.length - 1; i++) {
      if (index === i) {
        newNode.next = currentNode;
        prevNode.next = newNode;
        this.length++;
        return;
      }
      prevNode = currentNode;
      currentNode = currentNode.next;
    }  
  }

  toArray(){
    // Tu código aquí 👈
    const nodes = [];
    let currentNode = this.head;
    for (let i = 1; i <= this.length; i++) {
      nodes.push(currentNode.value);
      if (i < this.length)
        currentNode = currentNode.next;
    }
    return nodes;
  }

  removeAt(index){
    // Tu código aquí 👈
    if (index < 0 || index >= this.length)
      return null;
    if (index === 0) {
      this.delete(this.head.value);
      return;
    }
    let currentNode = this.head;
    let i = 1;
    while (currentNode.next) {
      if (index === i) {
        let retValue = currentNode.next.value;
        currentNode.next = currentNode.next.next;
        this.length--;
        return retValue;
      }
      currentNode = currentNode.next;
      i++;
    }
  }
}

💚Mi Solución💚

🛡️MURO ANTI-SPOILERS🛡️

🎯Nota

La mayoría de mi código esta comentado en algunas partes para comprender que se hace en cada bloque de código. Sin embargo, me gustaría puntualizar que en el método insertAt() las pruebas consideran un indice fuera de los límites el que sea igual a el length, en mi caso quise dejar mi código con el caso en el que es igual al length que en otras palabras es añadir a la cola.
Si requieren hacer pasar las pruebas solamente en el primer if de ese metodo es cambiar index > this.length por index >= this.length y eliminar el código del Caso2 (porque no se ocupa).
Sin duda alguna recorrer la SinglyLinkedList es fácil, pero lo dificil es insertar o remover los apuntadores a nodo siguiente. Recomiendo mucho hacer un dibujo con flechitas para que se observe como cambian los apuntadores.

👁️ Nota

En el método delete() proporcionado en clase no hay ningún problema al remover en medio o en cabeza. Sin embargo, al remover en cola el método si lo elimina efectivamente pero falta actualizar this.tail, solo sería agregar una validación para actualizarlo.

👾Código

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index) {
    if (index >= this.length || index < 0 )
      return null

    let actualNode = this.head;
    while (index > 0) {
      actualNode = actualNode.next
      index--
    }

    return actualNode.value 
  }

  insertAt(index, value) {
    if (index > this.length || index < 0)
      return null //Index out of bounds

    //Caso1: Se añade en la cabeza
    if (index == 0) {
      this.prepend(value)
      return
    }

    //Caso2: Se añade en la cola
    if (index == this.length) {
      this.append(value)
      return
    }

    //Caso3: Se añade en el medio
    let actualNode = this.head
    while (index > 1) {
      actualNode = actualNode.next
      index--
    }
    //El actualNode es un nodo antes de donde queremos insertar
    const nodeToInsert = new Node(value)
    const nextOfNodeToInsert = actualNode.next
    actualNode.next = nodeToInsert
    nodeToInsert.next = nextOfNodeToInsert
    this.length++
  }

  toArray() {
    const array = []
    let actualNode = this.head
    for (let i = 0; i < this.length; i++){
      array.push(actualNode.value)
      actualNode=actualNode.next
    }
    return array
  }

  removeAt(index) {
    if (index >= this.length || index < 0) 
      return null //Index out of bounds

    let value = null

    //Caso1: Se quiere eliminar la cabeza
    if (index === 0) {
      value = this.head.value
      this.head = this.head.next

      if (--this.length === 0) //Si eliminamos ya todo
        this.tail = null

      return value
    }

    //Caso2: Se quiere eliminar en medio o en cola

    //Obtenemos un nodo previo al que queremos eliminar
    let actualPrevNode = this.head;
    while (index > 1) {
      actualPrevNode = actualPrevNode.next
      index--
    }

    value = actualPrevNode.next.value
    //Hilamos al nodo siguiente del que queremos eliminar
    actualPrevNode.next = actualPrevNode.next.next

    //Caso3: En que el nodo que eliminamos fue la cola
    if (actualPrevNode.next === null)
      this.tail = actualPrevNode

    this.length--
    return value
  }
}

🛡️🛡️Escudo anti-spoilers🛡️🛡️
Mi solución al reto:

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index) {
    if (index < 0 || index > this.length - 1) return null
    let currentNode = this.head
    let counter = 0
    while (currentNode) {
      if (index === counter) return currentNode.value
      currentNode = currentNode.next
      counter++
    }
  }

  insertAt(index, value) {
    if (index < 0 || index > this.length - 1) return null
    let newNode = new Node(value)
    let currentNode = this.head
    let temp = null
    let lastNode = null
    //is head
    if (index === 0) {
      temp = currentNode
      this.head = newNode
      this.head.next = temp
      return true
    }
    let counter = 0
    while (currentNode) {
      if (index === counter) {
        temp = currentNode
        lastNode.next = newNode
        newNode.next = temp
        this.length++;
        return true
      }
      lastNode = currentNode
      currentNode = currentNode.next
      counter++
    }
    return false
  }

  toArray() {
    let myArray = []
    let currentNode = this.head
    while (currentNode) {
      myArray.push(currentNode.value)
      currentNode = currentNode.next
    }
    return myArray
  }

  removeAt(index) {
    if (index < 0 || index > this.length - 1) return null
    let currentNode = this.head
    let temp = null
    let lastNode = null
    let value = null
    //is head
    if (index === 0) {
      value = this.head.value
      this.head = this.head.next
      return value
    }

    let counter = 0
    while (currentNode) {
      if (index === counter) {
        value = currentNode.value
        temp = currentNode.next
        lastNode.next = temp
        return value
      }
      lastNode = currentNode
      currentNode = currentNode.next
      counter++
    }
  }
}
import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index){
    if (!this.head || index >= this.length || index < 0) {
      return null;
    }

    let node = this.head;
    let i = 0;
    while (i < index) {
      node = node.next;
      i++;
    }
    return node.value;
  }

  insertAt(index, value){
    if (!this.head || index >= this.length || index < 0) {
      return null;
    }

    let prevNode = null;
    let node = this.head;
    let i = 0;
    while (i < index) {
      prevNode = node;
      node = node.next;
      i++;
    }
    const newNode = new Node(value);
    if (prevNode) {
      prevNode.next = newNode;
    }
    newNode.next = node;
    node = newNode;
  }

  toArray(){
    if (!this.head) {
      return null;
    }
    const array = [];
    array.push(this.head.value);
    let currentNode = this.head;
    while (currentNode.next) {
      array.push(currentNode.next.value);
      currentNode = currentNode.next;
    }
    return array;
  }

  removeAt(index){
    if (!this.head || index >= this.length || index < 0) {
      return null;
    }

    let prevNode = null;
    let node = this.head;
    let i = 0;
    let value = null;
    while (i < index) {
      prevNode = node;
      node = node.next;
      i++;
    }
    value = node.value;
    if (prevNode) {
      prevNode.next = node.next;  
    }
    
    return value;
  }
}

MI SOLUCION 💪
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  getNodo(index) {
    if (index < 0 || index >= this.length) return null;
    let currentNodo = this.head;
    for (let i = 0; i < index; i++) {
      currentNodo = currentNodo.next;
    }
    return currentNodo;
  }

  get(index){
    const nodo = this.getNodo(index);
    return nodo ? nodo.value : null;
  }

  insertAt(index, value){
    if (index < 0 || index >= this.length) return null;
    if (index === 0) {
      this.prepend(value);
      return;
    }
    if (index === this.length - 1) {
      this.append(value);
      return;
    }
    const newNodo = new Node(value);
    const prevNodo = this.getNodo(index - 1);
    newNodo.next = prevNodo.next;
    prevNodo.next = newNodo;
    this.length++;
    return;
  }

  toArray() {
    const values = [];
    let currentNodo = this.head;
    for (let i = 0; i < this.length; i++) {
      values.push(currentNodo.value);
      currentNodo = currentNodo.next;
    }
    return values;
  }

  removeAt(index){
    if (index < 0 || index >= this.length) return null;
    const value = this.get(index);
    this.delete(value);
    return value;
  }
}
export class LinkedListRecharged extends LinkedList {
  get(index) {
    if (index < 0 || index >= this.length) {
      return null;
    }

    let current = this.head;
    for (let i = 0; i < index; i++) {
      current = current.next;
    }

    return current.value;
  }

  insertAt(index, value) {
    if (index < 0 || index >= this.length) {
      return null
    }

    const newNode = new Node(value)
    if (index === 0) {
      newNode.next = this.head
      this.head = newNode
      if (!this.tail) {
        this.tail = newNode
      }
      this.length++

      return newNode
    }
    let currentNode = this.head
    for (let i = 0; i < index - 1; i++) {
      currentNode = currentNode.next
    }

    newNode.next = currentNode.next
    currentNode.next = newNode

    if (!newNode.next) {
      this.tail = newNode
    }

    this.length++
    return newNode

  }

  toArray() {
    const arr = [];
    let current = this.head;
    while (current) {
      arr.push(current.value);
      current = current.next;
    }
    return arr;
  }

  removeAt(index) {
    if (index < 0 || index >= this.length) {
      return null;
    }

    let removedValue;
    if (index === 0) {
      removedValue = this.head.value;
      this.head = this.head.next;
    } else {
      let current = this.head;
      for (let i = 0; i < index - 1; i++) {
        current = current.next;
      }
      removedValue = current.next.value;
      current.next = current.next.next;
    }

    this.length--;
    return removedValue;
  }
}

Mi solución:
.
.
.
.
.
.
.
.

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index){
    if (index >= this.length || index < 0) {
     return null
    }
    let currentNode = this.head
    for (let i = 0; i < index; i++) {
      currentNode = currentNode.next
    }
    return currentNode.value
  }

  insertAt(index, value){
    if (index >= this.length || index < 0) {
      console.log(null)
      return null
    }
    if (index === 0) {
      this.prepend(value)
      return
    }
    if (index == this.length - 1) {
      this.append(value)
      return
    }
    let currentNode = this.head
    let nextNode = currentNode.next
    for (let i = 0; i < index - 1; i++) {
      currentNode = currentNode.next
      nextNode = currentNode.next
    }
    const newNode = new Node(value)
    currentNode.next = newNode
    newNode.next = nextNode
    this.length++
  }

  toArray(){
    let array = []
    let currentNode = this.head
    for (let i = 0; i < this.length; i++) {
      array.push(currentNode.value)
      currentNode = currentNode.next
    }
    return array
  }

  removeAt(index){
    const value = this.get(index)
    this.delete(value)
    return value
  }
}

Solución… 😄
.
Reto interesante, creo que el playground en el método ‘insertAt’ no permite insertar un nodo al final de la lista, porque el ‘index’ saldría fuera de rango.
.
Pero aún así adjunto la solución del playground y la solución que permite insertar un nodo al final de la lista utilizando el método ‘insertAt’ si lo quieren ver 😄.
.

.
Solución del playground:

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index) {
    if (index >= this.length || index < 0) {
      return null;
    }
    
    let currentNode = this.head;

    while (index) {
      currentNode = currentNode.next;
      index--;
    }

    return currentNode.value;
  }

  insertAt(index, value) {
    let newNode = new Node(value);

    if (index >= this.length || index < 0) {
      return null;
    }

    if (index === 0) {
      this.prepend(value);
      return this;
    }

    if (index === this.length) {
      this.append(value);
      return this;
    }

    let preNode = this.head;
    index--;

    while (index) {
      preNode = preNode.next;
      index--;
    }

    newNode.next = preNode.next;
    preNode.next = newNode;
    this.length++;
    return this;
  }

  toArray() {
    let currentNode = this.head;
    let res = [];

    while (currentNode) {
      res.push(currentNode.value);
      currentNode = currentNode.next;
    }

    return res;
  }

  removeAt(index) {
    if (index >= this.length || index < 0) {
      return null;
    }

    if (index === 0) {
      this.head = this.head.next;
      this.length--;
      return this;
    }

    let preNode = this.head;
    index--;

    while (index) {
      preNode = preNode.next;
      index--;
    }

    preNode.next = preNode.next.next;
    if (preNode.next === null) {
      this.tail = preNode;
    }
    
    this.length--;
    return this;
  }
}

.
Solución (no pasa la prueba del playground, pero se puede verificar en la pestaña 'Vista´ del mísmo) que permite agregar un nodo al final de la lista:

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index) {
    if (index >= this.length || index < 0) {
      return null;
    }
    
    let currentNode = this.head;

    while (index) {
      currentNode = currentNode.next;
      index--;
    }

    return currentNode.value;
  }

  insertAt(index, value) {
    let newNode = new Node(value);

    if (index > this.length || index < 0) {
      return null;
    }

    if (index === 0) {
      this.prepend(value);
      return this;
    }

    if (index === this.length) {
      this.append(value);
      return this;
    }

    let preNode = this.head;
    index--;

    while (index) {
      preNode = preNode.next;
      index--;
    }

    newNode.next = preNode.next;
    preNode.next = newNode;
    this.length++;
    return this;
  }

  toArray() {
    let currentNode = this.head;
    let res = [];

    while (currentNode) {
      res.push(currentNode.value);
      currentNode = currentNode.next;
    }

    return res;
  }

  removeAt(index) {
    if (index >= this.length || index < 0) {
      return null;
    }

    if (index === 0) {
      this.head = this.head.next;
      this.length--;
      return this;
    }

    let preNode = this.head;
    index--;

    while (index) {
      preNode = preNode.next;
      index--;
    }

    preNode.next = preNode.next.next;
    if (preNode.next === null) {
      this.tail = preNode;
    }
    
    this.length--;
    return this;
  }
} 

Mi solución:
Después de revisar otros algoritmos. Creo que mi propuesta es un poco más legible:
.
.
.
.
.
.
.

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index){
    let currentNode = this.head;
    if (index>=0&&index < this.length) {
      for (let i = 0; i < this.length; i++) {
        if (i !== index) {
          currentNode = currentNode.next
        } else {
          return currentNode.value
        }
      }
    } else {
      return null
    }   
  }

  insertAt(index, value){
    let currentNode = this.head;
    const newNode = new Node(value)
    if (index>=0&&index < this.length) {
      for (let i = 0; i < this.length; i++) {
        if (i !== index-1) {
          if (currentNode.next) currentNode = currentNode.next

        } else {
          newNode.next = currentNode.next
          currentNode.next=newNode
          this.length++
          return
        }
      }
    } else {
      return null
    }   
  }

  toArray(){
    const arrLinkedList = () => {
      const array = []
      let currentNode = this.head;
      for (let i = 0; i < this.length; i++) {
        array.push(currentNode.value)
        if (currentNode.next) currentNode = currentNode.next
      }
      return array
    }
    return arrLinkedList()
  }

  removeAt(index){
    let currentNode = this.head;
    if (index>=0&&index < this.length) {
      for (let i = 0; i < this.length; i++) {
        if (i !== index-1) {
          if (currentNode.next) currentNode = currentNode.next

        } else {
          const removed =  currentNode.next
          currentNode.next = currentNode.next.next
          this.length--
          return removed
        }
      }
    } else {
      return null
    }   
  }
}

Solucion

Necesite revisarlo muchas veces antes de entender bien el funcionamiento de los LinkedLists.
+
+
+
+
+
+
+
+
+
+

class LinkedListRecharged extends LinkedList {
  get(index) {
    // Tu código aquí 👈

    if (index < 0 || index > this.length) return null;

    let counter = 0;
    let currentNode = this.head;

    while (currentNode) {
      if (counter === index) {
        return currentNode;
      }
      currentNode = currentNode.next;
      counter++;
    }
  }

  insertAt(index, value) {
    // Tu código aquí 👈

    // Check for head and tail position
    if (index < 0 || index >= this.length) return null;

    // Create node

    // insert node at head
    if (index === 0) this.prepend(value);
    else if (index === this.length - 1) this.append(value);
    else {
      const newNode = new Node(value);
      const prevNode = this.get(index - 1);

      newNode.next = prevNode.next;
      prevNode.next = newNode;
      this.length++;

      return newNode;
    }
  }

  toArray() {
    // Tu código aquí 👈
    let arrayFromLinkedList = new Array(this.length);
    let currentNode = this.head;
    let i = 0;
    while (currentNode) {
      arrayFromLinkedList[i] = currentNode.value;
      currentNode = currentNode.next;
      i++;
    }
    console.log(arrayFromLinkedList);
    return arrayFromLinkedList;
  }

  removeAt(index) {
    // Tu código aquí 👈

    if (index < 0 || index >= this.length) return null;

    if (index === 0 || index === this.length - 1) {
      const deletedNode = this.get(index);
      this.delete(deletedNode.value);
      return deletedNode;
    } else {
      const prevNode = this.get(index - 1);
      const removedNode = prevNode.next;
      const realocatedNode = removedNode.next;

      prevNode.next = realocatedNode;
      this.length--;
      return removedNode.value;
    }
  }
}

Aquí mi solución:
.
.
.
.
.
.
.
.
.
.
.
.

class LinkedListRecharged extends LinkedList {
  get(index) {

    if (index < 0 && index > this.length) {
      return null;
    }

    if (!this.head) {
      return null;
    }

    let ii = 0;
    let currentNode = this.head;
    while (ii <= this.length) {
      if (ii === index) {
        return currentNode.value;
      }
      if (currentNode.next) {
        currentNode = currentNode.next;
        ii++
      } else {
        return null;
      }
    }
  }

  insertAt(index, value) {

    if (index < 0 && index > this.length) {
      return null;
    }

    if (!this.head) {
      return null;
    }

    let ii = 0;
    let currentNode = this.head;
    let newNode;
    let antNode;
    while (ii <= this.length) {
      if (ii === (index - 1)) {
        antNode = currentNode;
      } else if (ii === index) {
        newNode = new Node(value);
        newNode.next = currentNode;
        antNode.next = newNode;
        if (ii === 0) {
          this.head = newNode;
        } else if (ii === this.length) {
          this.tail = newNode;
        }
      }
      if (currentNode.next) {
        currentNode = currentNode.next;
        ii++
      } else {
        return null;
      }
    }
  }

  toArray() {
    let newarray = [];
    if (!this.head) {
      return null;
    }
    // Si el nodo a eliminar es el primer nodo en la lista
    // se recorre la lista buscando el nodo anterior al que se quiere eliminar
    let currentNode = this.head;
    while (currentNode.next) {
      newarray.push(currentNode.value)
      currentNode = currentNode.next;
    }
    newarray.push(currentNode.value)
    return newarray;
  }

  removeAt(index) {
    if (index <= 0 || index >= this.length) {
      return null;
    }

    if (!this.head) {
      return null;
    }

    if (index === 0) {
      this.head = this.head.next;
      this.length--;
      return this.length;
    }

    let ii = 0;
    let antNode;
    let currentNode = this.head;

    while (ii <= this.length) {
      if (ii === (index - 1)) {
        antNode = currentNode;
      } else if (ii === index) {
        if (currentNode.next) {
          antNode.next = currentNode.next
        } else {
          antNode.next = null
        }
        this.length--
        if (ii === this.length) {
          this.tail = newNode;
        }
        return this.length;
      }
      if (currentNode.next) {
        currentNode = currentNode.next;
        ii++
      }
    }
  }
}

,
,
,
,
,
,
,
,
,
,
,

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index) {
    if (index < 0 || index >= this.length) {
      return null;
    }
    let current = this.head;
    for (let i = 0; i < index; i++) {
      current = current.next;
    }
    return current.value;
  }

  insertAt(index, value) {
    if (index < 0 || index >= this.length) {
      return null;
    }
    const newNode = new Node(value);
    if (index === 0) {
      newNode.next = this.head;
      this.head = newNode;
    } else {
      let current = this.head;
      for (let i = 0; i < index - 1; i++) {
        current = current.next;
      }
      newNode.next = current.next;
      current.next = newNode;
    }
    this.length++;
    return newNode;
  }

  toArray() {
    const array = [];
    let current = this.head;
    while (current) {
      array.push(current.value);
      current = current.next;
    }
    return array;
  }

  removeAt(index) {
    if (index < 0 || index >= this.length) {
      return null;
    }
    let removedNode;
    if (index === 0) {
      removedNode = this.head;
      this.head = this.head.next;
    } else {
      let current = this.head;
      for (let i = 0; i < index - 1; i++) {
        current = current.next;
      }
      removedNode = current.next;
      current.next = current.next.next;
    }
    this.length--;
    return removedNode.value;
  }
}


Logre que mi solución quedara mas cortita que la solución 😄
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

excercise.js

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index) {
    if (index < 0 || index >= this.length) {
      return null
    }
    let i = 0;
    let currentNode = this.head;
    while (index !== i) {
      currentNode = currentNode.next;
      i++;
    }

    return currentNode.value;
  }

  insertAt(index, value) {
    if (index < 0 || index >= this.length) {
      return null
    }

    if (index >= this.length) {

      this.append(newNode);

    }
    const newNode = new Node(value);
    const firstPointer = this.getIndex(index - 1);
    const holdingPointer = firstPointer.next;
    firstPointer.next = newNode;
    newNode.next = holdingPointer;

    this.length++;
  }

  toArray() {
    let currentNode = this.head;
    let i = 0;
    let array = [];
    while (i < this.length) {
      array.push(currentNode.value);
      currentNode = currentNode.next;
      i++;
    }
    return array;
  }

  removeAt(index) {
    if (index < 0 || index >= this.length) {
      return null
    }
    const firstPointer = this.getIndex(index - 1);
    const holdingPointer = this.getIndex(index + 1);
    firstPointer.next = holdingPointer;

    this.length--;
    return this;

  }
  getIndex(index) {
    if (index < 0 || index >= this.length) {
      return null
    }
    let i = 0;
    let currentNode = this.head;
    while (index !== i) {
      currentNode = currentNode.next;
      i++;
    }

    return currentNode;
  }
} 

🛡️🛡️🛡️Escudo anti spoilers🛡️🛡️🛡️

Agrega métodos a singly linked list

Decidí complicarme la vida y hacerlo con recursividad y closures 😂 a continuación mi solución explicada con comentarios casi en cada línea tratando de que sea lo mas entendible posible

Nunca pares de aprender 🦾

get(index)

get(index) {
  // Si el index es < 0 o > length se levanta un error
  if (index < 0 || index > this.length - 1) {
    return null
  }

  // Variable para almacenar profundiad actual
  let actual = this;

  // Funcion recursiva para subir capas
  function getValue() {
    // Si está en el head el actual es el primer nodo
    if (actual.head) {
      actual = actual.head;
    }
    // Si no está en el head diminuye el index y asigna al siguiente nodo como el actual
    else {
      index = index - 1;
      actual = actual.next;
    }
    // En caso de que el index llegue a 0 se retorna el valor del nodo
    if (index == 0) {
      return actual.value;
    }
    // Se vuelve a llamar la función dentro de la recurrencia
    return getValue();
  }
  // Se llama la funcion desde get(index)
  return getValue();
}

insertAt(index,value)

insertAt(index, value) {
  // Si el index es < 0 o > length se levanta un error
  if (index < 0 || index > this.length - 1) {
    return null
  }

  // Variable para almacenar profundiad actual
  let actual = this;
  // Se aumenta en 1 a la longitud de la lista
  this.length++;
  // Funcion recursiva para subir capas
  function appendValue() {
    // Si está en el head el actual es el primer nodo
    if (actual.head) {
      actual = actual.head;
    }
    // Si no está en el head diminuye el index y asigna al siguiente nodo como el actual
    else {
      index = index - 1;
      actual = actual.next;
    }
    // En caso de que el index llegue a 0 quiere decir que estamos en la posicion a insertar
    if (index == 0) {
      // Se crea una nueva instancia de nodo con el valor a insertar
      let oldNode = new Node(actual.value);
      // Se "COPIA" todo el contenido del nodo en el que estamos a el nodo anterior
      oldNode.next = actual.next;
      // Se reemplaza el nodo actual con el valor que llega por parametro
      actual.value = value;
      // Se reemplaza el siguiente nodo con el nodo creado
      actual.next = oldNode;
      // Se retorna el valor insertado
      return value;
    }
    // Se vuelve a llamar la función dentro de la recurrencia
    return appendValue();
  }
  // Se llama la funcion desde insertAt(index, value)
  return appendValue();
}

toArray()

toArray() {
  // Variable para almacenar profundiad actual y array a retornar
  let actual = this;
  const arr = [];

  // Funcion recursiva para subir capas
  function pushToArray() {
    // Si está en el head el actual es el primer nodo
    if (actual.head) {
      actual = actual.head;
    }
    // Se actual.next es null quiere decir que es la ultima capa
    // Entonces se agrega el ultmo valor y se retorna el arreglo
    if (actual.next == null) {
      arr.push(actual.value);
      return arr;
    }
    // Si no está en el head diminuye el index y asigna al siguiente nodo como el actual
    else {
      arr.push(actual.value);
      actual = actual.next;
    }
    // Se vuelve a llamar la función dentro de la recurrencia
    return pushToArray();
  }
  // Se llama la funcion desde toArray()
  return pushToArray();
}

removeAt(index)

removeAt(index) {
  // Si el index es < 0 o > length se levanta un error
  if (index < 0 || index > this.length - 1) {
    return null
  }

  // Variable para almacenar profundiad actual
  let actual = this;
  // Se disminuye en 1 a la longitud de la lista
  this.length--;
  // Funcion recursiva para subir capas
  function deleteValue() {
    // Si está en el head el actual es el primer nodo
    if (actual.head) {
      actual = actual.head;
    }
    // Si no está en el head diminuye el index y asigna al siguiente nodo como el actual
    else {
      index = index - 1;
      actual = actual.next;
    }
    // En caso de que el index llegue a 0 quiere decir que estamos en la posicion a eliminar
    if (index == 0) {
      // Se crea una nueva instancia de nodo excluyendo el valor a eliminar
      const newNode = new Node(actual.next.value)
      newNode.next = actual.next.next
      actual.value = newNode.value
      actual.next = newNode.next
      // Se retorna el valor eliminado
      return;
    }
    // Se vuelve a llamar la función dentro de la recurrencia
    return deleteValue();
  }
  // Se llama la funcion desde insertAt(index, value)
  return deleteValue();
}

Les dejo mi solución. Deben tener en cuenta que si se indica un indice que está fuera de rango, los métodos deben devolver null para que no les de error. Ahora si:
.
.
.
.
.
.
.
.
.
.
.
.
.
.

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  
  get(index){
    if (!this.head) {
      return null;
    }
    if (index < 0 || index >= this.length) return null;
    if (index === 0) return this.head.value;
    if (index === this.length - 1) return this.tail.value;
    let cont = 0;
    let currentNode = this.head;
    while (currentNode) {
      if (cont === index) return currentNode.value;
      cont++;
      currentNode = currentNode.next;
      }
  }

  insertAt(index, value) {
    if (index < 0 || index >= this.length) return null;
    if (!this.head) {
      super.append(value);
    }
    if (index === 0) super.prepend(value);
    if (index === this.length - 1) super.append(value);
    let cont = 1;
    let currentNode = this.head;
    while (currentNode.next) {
      if (cont === index) {
        const newNode = new Node(value);
        newNode.next = currentNode.next;
        currentNode.next = newNode
        this.length++;
        break;
      }
      cont++;
      currentNode = currentNode.next;
    }
  }

  toArray(){
    if (this.length === 0) return [];
    let newArray = [this.head.value];
    let currentNode = this.head;
    while (currentNode.next) {
      newArray.push(currentNode.next.value);
      currentNode = currentNode.next;
    }
    return newArray;
  }

  removeAt(index) {
    if (index < 0 || index >= this.length) return null;
    if (!this.head) {
      return null;
    }
    if (index === 0) super.delete(this.head.value);
    if (index === this.lenght - 1) super.delete(this.tail.value);
    let cont = 0;
    let currentNode = this.head;
    while (currentNode) {
      if (cont === index) super.delete(currentNode.value);
      cont++;
      currentNode = currentNode.next;
    }
  }
}

Mi solucion
.
.
.
.
.
.
.
.
.
.
.
.
.
.

import { LinkedList } from "./SinglyLinkedList";
import { Node } from "./Node";

export class LinkedListRecharged extends LinkedList {
  get(index){
    if(index < 0 || index >= this.length){
      return null
    }

    let currentNode = this.head
    for (let i = 0; i < index; i++) {
      currentNode = currentNode.next
    }

    return currentNode.value
  }

  insertAt(index, value){
    if(index < 0 || index >= this.length){
      return null
    }

    const newNode = new Node(value)
    if(index === 0){
      newNode.next = this.head 
      this.head = newNode
      if(!this.tail){
        this.tail = newNode
      }
      this.length++

      return newNode
    }
    let currentNode = this.head
    for(let i = 0; i < index - 1; i++){
      currentNode = currentNode.next
    }

    newNode.next = currentNode.next
    currentNode.next = newNode    

    if(!newNode.next){
      this.tail = newNode
    }

    this.length++
    return newNode

  }

  toArray(){
    const result = []
    let currentNode = this.head
    while(currentNode){
      result.push(currentNode.value)
      currentNode = currentNode.next
    }

    return result
  }

  removeAt(index){
    if(index < 0 || index >= this.length){
      return null
    }

    let deletedNode = null
    if(index === 0){
      deletedNode = this.head
      this.head = this.head.next
      if(this.length === 1){
        this.tail = null
      }
      this.length--
      return deletedNode.value
    }

    let currentNode = this.head

    for (let i = 0; i < index - 1; i++) {
      currentNode = currentNode.next
    }

    deletedNode = currentNode.next
    currentNode.next = currentNode.next.next

    if(!currentNode.next){
      this.tail = currentNode
    }

    this.length--
    return deletedNode.value
  }
}

undefined