了解 *这个 *内部课程的上下文

发布于 2025-01-23 11:58:58 字数 2289 浏览 0 评论 0原文

我有以下代码。

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

在上面的this.Children变量设置正确。如果我直接保存this.Children数组,而无需将其包裹在功能中,则我会看到设置不正确的孩子。

示例:

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

我知道,如果没有功能包装器, 的上下文就不会有意见。我不明白的是原因。有什么想法吗?

在第一个示例上调用getChildRenvalues返回[“ a”,“ b”,“ c”]。

调用getChildrenvalues在第二个示例上返回[“ 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())

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())

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蓝天 2025-01-30 11:58:58

我知道,如果没有功能包装器,的上下文是不一致的。我不明白的是为什么?

这与关键字无关。由于您使用了箭头函数,因此确实指的是两个代码段中的完全相同的对象,因此没有区别。

从两个片段中获得不同结果的原因是懒惰的执行,但与有关,而是possiblechildren array。在您的第一个代码中,while(possiblechildren.length> 0)运行并清空possiblechildren array array 您进行递归新节点调用。在第二个示例中,您在期间调用new Node ,然后传递对 same same possibleChildren 数组,由递归调用倒空,因此循环在第一次迭代后立即终止。

要解决此问题,只是不要递归传递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())

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())

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文