Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

230
Views
Understanding the context of *this* inside classes

I have the following code.

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);
  }
}

In the above the this.children variable is set properly. If I save the this.children array directly, without wrapping it in a function, I see incorrect children being set.

Example:

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);
  }
}

I know that the context of this is not consitent without the function wrapper. What I do not understand is why. Any ideas?

Calling getChildrenValues on the first example returns ["A", "B", "C"].

Calling getChildrenValues on the second example returns ["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())

about 4 years ago · Santiago Trujillo
1 answers
Answer question

0

I know that the context of this is not consistent without the function wrapper. What I do not understand is why?

This has nothing to do with the this keyword. Since you used an arrow function, it does refer to exactly the same object in both your code snippets, there is no difference.

The reason why you get different results from the two snippets is the lazy execution, but not with respect to this, but rather the possibleChildren array. In your first code, the while (possibleChildren.length > 0) runs and empties the possibleChildren array before you do the recursive new Node calls. In the second example, you call new Node during that loop, and you pass on the reference to the same possibleChildren array, which is being emptied by the recursive call and the loop therefore terminates right after the first iteration.

To fix this, just don't recursively pass the 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())

about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!