tengo el siguiente código.
class Node { constructor(value, parent, possibleChildren = []) { this.value = value; this.parent = parent; this.children = [] this.setChildren(possibleChildren); } setChildren(possibleChildren) { if (possibleChildren.length === 0) return []; while (possibleChildren.length > 0) { const value = possibleChildren.pop(); // keyword *this* messes up the context. Save them function calls for lazy execution let childNode = () => new Node(value, this, possibleChildren); this.children.push(childNode); } this.children = this.children.map(child => child()) } getChildrenValues() { return this.children.map((child) => child.value); } } En lo anterior, la variable this.children está configurada correctamente. Si guardo la matriz this.children directamente, sin envolverla en una función, veo que se configuran elementos secundarios incorrectos.
Ejemplo:
setChildren(possibleChildren) { if (possibleChildren.length === 0) return []; while (possibleChildren.length > 0) { const value = possibleChildren.pop(); // keyword *this* messes up the context. Save them function calls for lazy execution let childNode = new Node(value, this, possibleChildren); this.children.push(childNode); } }Sé que el contexto de esto no es consistente sin el contenedor de funciones. Lo que no entiendo es por qué. ¿Algunas ideas?
Llamar a getChildrenValues en el primer ejemplo devuelve ["A", "B", "C"].
Llamar a getChildrenValues en el segundo ejemplo devuelve ["C"]
class Node { constructor(value, parent, possibleChildren = []) { this.value = value; this.parent = parent; this.children = [] this.setChildren(possibleChildren); } setChildren(possibleChildren) { if (possibleChildren.length === 0) return []; while (possibleChildren.length > 0) { const value = possibleChildren.pop(); // keyword *this* messes up the context. Save them function calls for lazy execution const childNode = new Node(value, this, possibleChildren); this.children.push(childNode); } } getChildrenValues() { return this.children.map((child) => child.value); } } let root = new Node(null, null, "ABC".split("")); console.log(root.getChildrenValues())Sé que el contexto de
thisno es consistente sin el contenedor de funciones. Lo que no entiendo es ¿por qué?
Esto no tiene nada que ver con la palabra clave this . Dado que usó una función de flecha, se refiere exactamente al mismo objeto en ambos fragmentos de código, no hay diferencia.
La razón por la que obtiene resultados diferentes de los dos fragmentos es la ejecución diferida, pero no con respecto a this , sino a la matriz possibleChildren . En su primer código, while (possibleChildren.length > 0) se ejecuta y vacía la matriz de possibleChildren niños antes de realizar las new Node recursivas. En el segundo ejemplo, llamas a new Node durante ese ciclo y pasas la referencia a la misma matriz de possibleChildren niños, que está siendo vaciada por la llamada recursiva y, por lo tanto, el ciclo termina justo después de la primera iteración.
Para arreglar esto, simplemente no pase recursivamente los possibleChildren :
class Node { constructor(value, parent, childrenValues = []) { this.value = value; this.parent = parent; this.children = [] this.setChildrenValues(childrenValues); } setChildrenValues(childrenValues) { for (let i=childrenValues.length; i--; ) { const value = childrenValues[i]; const childNode = new Node(value, this ); // ^ no third argument, no grandchildren this.children.push(childNode); } } getChildrenValues() { return this.children.map((child) => child.value); } } let root = new Node(null, null, "ABC".split("")); console.log(root.getChildrenValues())